在Java中,sleep
和wait
是两个常用的暂停线程执行的方法,但它们有不同的功能和使用场景。理解它们的区别对于多线程编程非常重要。
sleep
方法
定义
sleep
是Thread
类的静态方法,用于让当前线程休眠指定的时间。sleep
不释放锁。
特点
- 静态方法:
sleep
是Thread
类的静态方法。 - 暂停时间:
sleep
接受一个时间参数(以毫秒为单位),指定线程暂停的时间。 - 不释放锁:当线程在同步代码块或方法中调用
sleep
时,它不会释放已持有的锁。 - 中断:
sleep
可能会抛出InterruptedException
,因此需要处理此异常。 - 无需同步:
sleep
方法无需在同步块中调用。
示例
public class SleepExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
try {
System.out.println("Thread is going to sleep");
Thread.sleep(2000); // 线程休眠2秒
System.out.println("Thread woke up");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
thread.start();
}
}
wait
方法
定义
wait
是Object
类的实例方法,用于暂停线程的执行,直到另一个线程调用同一个对象的notify
或notifyAll
方法。wait
必须在同步代码块或同步方法中调用,并且它释放锁。
特点
- 实例方法:
wait
是Object
类的实例方法。 - 释放锁:当线程调用
wait
时,它会释放当前对象的锁。 - 必须在同步块中调用:
wait
方法必须在同步块或同步方法中调用。 - 中断:
wait
可能会抛出InterruptedException
,因此需要处理此异常。 - 等待通知:线程会一直等待,直到收到通知(
notify
或notifyAll
),或被中断。
示例
public class WaitExample {
public static void main(String[] args) {
final Object lock = new Object();
Thread thread1 = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("Thread 1 is waiting");
lock.wait(); // 线程1等待
System.out.println("Thread 1 is resumed");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread thread2 = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("Thread 2 is sleeping for 2 seconds");
Thread.sleep(2000); // 线程2休眠2秒
System.out.println("Thread 2 is notifying");
lock.notify(); // 线程2通知
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread1.start();
thread2.start();
}
}
主要区别
-
所属类:
sleep
:属于Thread
类。wait
:属于Object
类。
-
同步要求:
sleep
:不需要在同步块中调用。wait
:必须在同步块或同步方法中调用。
-
锁处理:
sleep
:不会释放锁。wait
:会释放当前对象的锁。
-
目的:
sleep
:用于暂停当前线程一段时间。wait
:用于线程间通信,等待某个条件发生变化(通常由另一个线程通知)。
-
唤醒:
sleep
:在指定的时间过后自动唤醒。wait
:需要调用notify
或notifyAll
方法来唤醒,或被中断。
-
中断处理:
sleep
:抛出InterruptedException
。wait
:抛出InterruptedException
。
总结
- 使用
Thread.sleep
来让当前线程暂停执行一段指定的时间,不涉及线程间的协作。 - 使用
Object.wait
和Object.notify/notifyAll
来实现线程间的协作,等待某个条件的改变,并且在调用wait
时必须获取到对象的监视器锁。
了解并正确使用这两种方法,可以在多线程编程中有效地控制线程的执行和通信。