Sleep 和 Wait 的区别
Sleep(Thread.sleep())
一、是什么?
Thread.sleep()
是 Thread
类的静态方法,使当前线程暂停执行指定时间(毫秒/纳秒),不释放锁,时间结束后自动恢复运行。
二、解决什么问题
解决需要让线程暂停执行一段时间的场景(如模拟延迟、定时任务),但不影响其他线程对共享资源的访问(因为不释放锁)。
三、核心方法
java
Thread.sleep(long millis); // 毫秒
Thread.sleep(long millis, int nanos); // 毫秒+纳秒
四、应用场景
- 模拟网络请求延迟
- 定时轮询(如每隔 5 秒检查状态)
- 控制动画帧率(游戏开发)
五、Java 示例
java
public class SleepExample {
public static void main(String[] args) {
new Thread(() -> {
synchronized (SleepExample.class) {
System.out.println("Thread 1: 持有锁,休眠 2 秒");
try {
Thread.sleep(2000); // 休眠但不释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread 1: 唤醒");
}
}).start();
new Thread(() -> {
synchronized (SleepExample.class) {
System.out.println("Thread 2: 获得锁"); // 需等待 Thread 1 释放锁
}
}).start();
}
}
六、重要注意事项
- 必须捕获
InterruptedException
- 是静态方法,作用于当前线程
- 不释放锁,其他线程无法进入同步块
Wait(Object.wait())
一、是什么?
Object.wait()
是 Object
类的方法,使当前线程释放锁并进入等待状态,需通过 notify()
/notifyAll()
唤醒。
二、解决什么问题
解决线程间协作问题(如生产者-消费者模型),让线程在条件不满足时主动释放锁,避免资源浪费。
三、核心方法
java
object.wait(); // 无限等待
object.wait(long timeout); // 超时等待
四、应用场景
- 生产者-消费者队列(缓冲区空/满时等待)
- 线程池任务调度
- 多线程条件检查(如等待初始化完成)
五、Java 示例
java
public class WaitExample {
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
new Thread(() -> {
synchronized (lock) {
System.out.println("Thread 1: 等待通知...");
try {
lock.wait(); // 释放锁并等待
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread 1: 收到通知,继续执行");
}
}).start();
Thread.sleep(1000); // 确保 Thread 1 先执行
new Thread(() -> {
synchronized (lock) {
System.out.println("Thread 2: 发送通知");
lock.notify(); // 唤醒等待线程
}
}).start();
}
}
六、重要注意事项
- 必须在
synchronized
块中调用 - 唤醒后需重新竞争锁
- 使用
while
循环检查条件(避免虚假唤醒)
Sleep 和 Wait 的核心区别
特性 | Sleep | Wait |
---|---|---|
所属类 | Thread 类 | Object 类 |
锁释放 | ❌ 不释放锁 | ✅ 释放锁 |
调用要求 | 任意场景 | 必须在 synchronized 块中 |
唤醒方式 | 超时后自动唤醒 | 需 notify() /notifyAll() 唤醒 |
使用场景 | 单纯的时间延迟 | 线程间协作 |
异常捕获 | 必须捕获 InterruptedException | 必须捕获 InterruptedException |
总结
- 用
sleep
当需要纯暂停:不涉及线程协作,只是让当前线程“睡一会”(如倒计时)。 - 用
wait
当需要线程协作:涉及共享资源条件判断(如队列空/满),需释放锁让其他线程工作。 - 关键区别:
sleep
是“抱着锁睡觉”,wait
是“释放锁等人叫醒”。实际开发中,wait
通常与同步机制配合使用,而sleep
更适用于独立延迟任务。 - JDK 8+ 提示:优先考虑
java.util.concurrent
包的工具(如Semaphore
、CountDownLatch
)替代裸wait/notify
,减少错误风险。