Java 中 sleep 和 wait 之间的区别?

简介: 【8月更文挑战第21天】

在 Java 编程中,sleepwait都是用于控制线程执行的方法,但它们之间存在着一些重要的区别。理解这些区别对于正确地编写多线程程序至关重要。

一、sleep方法

  1. 定义和用法

    • sleepThread类的静态方法,它的作用是使当前正在执行的线程暂停指定的时间(以毫秒为单位)。在暂停期间,线程会进入阻塞状态,不会占用 CPU 资源。当指定的时间过去后,线程会自动恢复执行。
    • 例如:Thread.sleep(1000);表示让当前线程暂停 1 秒钟。
  2. 应用场景

    • sleep方法通常用于模拟延迟或等待一段时间后再执行某些操作。例如,在一个游戏程序中,可以使用sleep方法来控制动画的帧率,或者在一个网络应用程序中,可以使用sleep方法来模拟网络延迟。
  3. 特点

    • sleep方法不会释放锁。如果一个线程在持有某个对象的锁的情况下调用sleep方法,那么它会一直持有这个锁,直到sleep方法结束。这意味着其他线程如果需要获取这个锁,就必须等待当前线程完成sleep方法。
    • sleep方法是可中断的。如果一个线程在sleep期间被其他线程调用了interrupt方法,那么它会抛出InterruptedException异常,并立即结束sleep状态。

二、wait方法

  1. 定义和用法

    • waitObject类的方法,它的作用是使当前线程进入等待状态,直到其他线程调用同一个对象的notifynotifyAll方法来唤醒它。在等待期间,线程会释放它所持有的对象的锁,以便其他线程可以获取这个锁并执行相应的操作。
    • 例如:synchronized(obj) { obj.wait(); }表示当前线程在持有对象obj的锁的情况下进入等待状态,直到其他线程调用obj.notify()obj.notifyAll()方法来唤醒它。
  2. 应用场景

    • wait方法通常用于实现线程间的协作和通信。例如,在一个生产者-消费者模型中,生产者线程在生产完一个产品后,可以调用wait方法进入等待状态,直到消费者线程消费了这个产品并调用notify方法来唤醒它。
  3. 特点

    • wait方法必须在同步代码块中调用。这是因为wait方法会释放对象的锁,而只有在持有锁的情况下才能释放锁。如果在非同步代码块中调用wait方法,会抛出IllegalMonitorStateException异常。
    • wait方法可以设置超时时间。可以使用wait(long timeout)方法来指定线程等待的最长时间,如果在超时时间内没有被唤醒,线程会自动结束等待状态。
    • wait方法只能被同一个对象的notifynotifyAll方法唤醒。如果一个线程在等待一个对象的wait方法,那么只有当其他线程调用了同一个对象的notifynotifyAll方法时,这个线程才会被唤醒。

三、sleepwait的区别总结

  1. 所属类不同

    • sleepThread类的静态方法,而waitObject类的方法。
  2. 释放锁的行为不同

    • sleep方法不会释放锁,而wait方法会释放锁。
  3. 调用方式不同

    • sleep方法可以在任何地方调用,而wait方法必须在同步代码块中调用。
  4. 唤醒方式不同

    • sleep方法会在指定的时间过去后自动恢复执行,而wait方法必须等待其他线程调用同一个对象的notifynotifyAll方法才能被唤醒。
  5. 是否可中断不同

    • sleep方法是可中断的,而wait方法在等待期间可以被其他线程中断,但中断后会抛出InterruptedException异常,需要在代码中进行处理。

四、示例代码

以下是一个使用sleepwait方法的示例代码,展示了它们在多线程编程中的不同应用场景:

public class SleepWaitExample {
   
    public static void main(String[] args) {
   
        Object obj = new Object();

        Thread t1 = new Thread(() -> {
   
            synchronized (obj) {
   
                System.out.println("Thread 1: Entered synchronized block.");
                try {
   
                    // 使用 wait 方法进入等待状态
                    obj.wait();
                } catch (InterruptedException e) {
   
                    e.printStackTrace();
                }
                System.out.println("Thread 1: Resumed after wait.");
            }
        });

        Thread t2 = new Thread(() -> {
   
            synchronized (obj) {
   
                System.out.println("Thread 2: Entered synchronized block.");
                try {
   
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
   
                    e.printStackTrace();
                }
                // 使用 notify 方法唤醒等待的线程
                obj.notify();
                System.out.println("Thread 2: Sent notify.");
            }
        });

        t1.start();
        t2.start();
    }
}

在这个例子中,线程t1在持有对象obj的锁的情况下调用wait方法进入等待状态,线程t2在持有对象obj的锁的情况下调用sleep方法暂停 2 秒钟,然后调用notify方法唤醒等待的线程t1

总之,sleepwait方法在 Java 多线程编程中都有各自的用途,但它们之间存在着明显的区别。正确地理解和使用这些方法可以帮助开发人员更好地控制线程的执行,实现高效的多线程程序。

目录
相关文章
|
5天前
|
安全 Java 程序员
Java面试必问!run() 和 start() 方法到底有啥区别?
在多线程编程中,run和 start方法常常让开发者感到困惑。为什么调用 start 才能启动线程,而直接调用 run只是普通方法调用?这篇文章将通过一个简单的例子,详细解析这两者的区别,帮助你在面试中脱颖而出,理解多线程背后的机制和原理。
37 12
|
1月前
|
Java
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
今日分享的主题是如何区分&和&&的区别,提高自身面试的能力。主要分为以下四部分。 1、自我面试经历 2、&amp和&amp&amp的不同之处 3、&对&&的不同用回答逻辑解释 4、彩蛋
|
2月前
|
Java 程序员
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
小米,29岁程序员,分享了一次面试经历,详细解析了Java中&和&&的区别及应用场景,展示了扎实的基础知识和良好的应变能力,最终成功获得Offer。
98 14
|
1月前
|
Java
java中面向过程和面向对象区别?
java中面向过程和面向对象区别?
31 1
|
2月前
|
存储 缓存 安全
java 中操作字符串都有哪些类,它们之间有什么区别
Java中操作字符串的类主要有String、StringBuilder和StringBuffer。String是不可变的,每次操作都会生成新对象;StringBuilder和StringBuffer都是可变的,但StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此性能略低。
83 8
|
2月前
|
安全 Java
Java中WAIT和NOTIFY方法调用时机的深层解析
在Java多线程编程中,`wait()`和`notify()`方法的正确使用对于线程间的协调至关重要。这两个方法必须在同步块或同步方法中调用,这一规定的深层原因是什么呢?本文将深入探讨这一机制。
58 5
|
2月前
|
安全 Java 开发者
Java中WAIT和NOTIFY方法必须在同步块中调用的原因
在Java多线程编程中,`wait()`和`notify()`方法是实现线程间协作的关键。这两个方法必须在同步块或同步方法中调用,这一要求背后有着深刻的原因。本文将深入探讨为什么`wait()`和`notify()`方法必须在同步块中调用,以及这一机制如何确保线程安全和避免死锁。
65 4
|
2月前
|
安全 Java 开发者
深入解读JAVA多线程:wait()、notify()、notifyAll()的奥秘
在Java多线程编程中,`wait()`、`notify()`和`notifyAll()`方法是实现线程间通信和同步的关键机制。这些方法定义在`java.lang.Object`类中,每个Java对象都可以作为线程间通信的媒介。本文将详细解析这三个方法的使用方法和最佳实践,帮助开发者更高效地进行多线程编程。 示例代码展示了如何在同步方法中使用这些方法,确保线程安全和高效的通信。
91 9
|
2月前
|
Java
JAVA多线程通信:为何wait()与notify()如此重要?
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是实现线程间通信的核心机制。它们通过基于锁的方式,使线程在条件不满足时进入休眠状态,并在条件满足时被唤醒,从而确保数据一致性和同步。相比其他通信方式,如忙等待,这些方法更高效灵活。 示例代码展示了如何在生产者-消费者模型中使用这些方法实现线程间的协调和同步。
46 3
|
2月前
|
Java
Java代码解释++i和i++的五个主要区别
本文介绍了前缀递增(++i)和后缀递增(i++)的区别。两者在独立语句中无差异,但在赋值表达式中,i++ 返回原值,++i 返回新值;在复杂表达式中计算顺序不同;在循环中虽结果相同但使用方式有别。最后通过 `Counter` 类模拟了两者的内部实现原理。
Java代码解释++i和i++的五个主要区别