wait()和sleep()的区别:新手最容易混淆的概念
特性sleep()wait()所属Thread类静态方法Object类实例方法锁处理不释放锁释放锁使用位置任何地方synchronized块中唤醒方式时间到或中断主要用途暂停执行线程通信典型场景延迟、轮询生产者消费者。
Java并发编程初级系列第8篇 wait()和sleep()都可以让线程暂停执行,但它们的工作原理和使用场景完全不同。这是Java并发编程中新手最容易混淆的概念之一。本文将详细解释它们的区别和正确用法。
🤔 初学者的困惑
看似相似的功能
public class ConfusionExample {
/**
* 新手常见的困惑
*/
public static void demonstrateConfusion() {
System.out.println("=== 新手常见困惑 ===");
// 都可以让线程暂停
System.out.println("Thread.sleep(1000) - 让线程睡眠1秒");
System.out.println("object.wait(1000) - 让线程等待1秒");
System.out.println("\n看起来功能相似,但实际上完全不同!");
// 错误的理解
System.out.println("\n❌ 错误理解:");
System.out.println("- 都是让线程暂停执行");
System.out.println("- 可以互相替换使用");
System.out.println("- 效果基本相同");
// 正确的理解
System.out.println("\n✅ 正确理解:");
System.out.println("- sleep()是Thread类的静态方法");
System.out.println("- wait()是Object类的实例方法");
System.out.println("- 它们的使用场景和机制完全不同");
System.out.println("- 对锁的处理方式不同");
System.out.println("- 唤醒方式不同");
}
public static void main(String[] args) {
demonstrateConfusion();
}
}
😴 sleep()详解
sleep()的工作原理
public class SleepDetails {
/**
* sleep()基本用法演示
*/
public static void demonstrateSleepBasics() throws InterruptedException {
System.out.println("=== sleep()基本用法 ===");
System.out.println("开始时间: " + new Date());
// Thread.sleep()让当前线程暂停执行
System.out.println("线程开始睡眠2秒...");
Thread.sleep(2000);
System.out.println("线程醒来了!");
System.out.println("结束时间: " + new Date());
}
/**
* sleep()不会释放锁
*/
public static void demonstrateSleepWithLock() throws InterruptedException {
System.out.println("\n=== sleep()不会释放锁 ===");
Object lock = new Object();
// 线程1:持有锁并睡眠
Thread thread1 = new Thread(() -> {
synchronized (lock) {
System.out.println("线程1:获得锁,开始睡眠...");
try {
Thread.sleep(3000); // 睡眠时不释放锁
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("线程1:睡眠结束,释放锁");
}
}, "Thread-1");
// 线程2:尝试获取同一个锁
Thread thread2 = new Thread(() -> {
System.out.println("线程2:尝试获取锁...");
synchronized (lock) {
System.out.println("线程2:获得锁!");
}
}, "Thread-2");
thread1.start();
Thread.sleep(100); // 确保线程1先启动
thread2.start();
thread1.join();
thread2.join();
System.out.println("观察:线程2必须等待线程1睡眠结束才能获得锁");
}
/**
* sleep()可以被中断
*/
public static void demonstrateSleepInterruption() throws InterruptedException {
System.out.println("\n=== sleep()可以被中断 ===");
Thread sleepingThread = new Thread(() -> {
try {
System.out.println("开始长时间睡眠...");
Thread.sleep(10000); // 睡眠10秒
System.out.println("睡眠正常结束");
} catch (InterruptedException e) {
System.out.println("睡眠被中断!");
Thread.currentThread().interrupt(); // 恢复中断状态
}
}, "SleepingThread");
sleepingThread.start();
// 2秒后中断睡眠
Thread.sleep(2000);
System.out.println("中断睡眠线程...");
sleepingThread.interrupt();
sleepingThread.join();
}
/**
* sleep()的不同重载方法
*/
public static void demonstrateSleepOverloads() throws InterruptedException {
System.out.println("\n=== sleep()的重载方法 ===");
// 毫秒级睡眠
System.out.println("毫秒级睡眠开始");
Thread.sleep(1000); // 1秒
System.out.println("毫秒级睡眠结束");
// 纳秒级睡眠(实际精度取决于系统)
System.out.println("纳秒级睡眠开始");
Thread.sleep(0, 500000); // 0毫秒 + 500000纳秒 = 0.5毫秒
System.out.println("纳秒级睡眠结束");
System.out.println("注意:纳秒级精度在大多数系统上并不准确");
}
public static void main(String[] args) throws InterruptedException {
demonstrateSleepBasics();
demonstrateSleepWithLock();
demonstrateSleepInterruption();
demonstrateSleepOverloads();
}
}
⏰ wait()详解
wait()的工作原理
public class WaitDetails {
/**
* wait()基本用法演示
*/
public static void demonstrateWaitBasics() throws InterruptedException {
System.out.println("=== wait()基本用法 ===");
Object lock = new Object();
// 等待线程
Thread waitingThread = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("等待线程:开始等待...");
lock.wait(); // 释放锁并等待
System.out.println("等待线程:被唤醒了!");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}, "WaitingThread");
// 唤醒线程
Thread notifyingThread = new Thread(() -> {
try {
Thread.sleep(2000); // 等待2秒
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
synchronized (lock) {
System.out.println("唤醒线程:发送通知...");
lock.notify(); // 唤醒等待的线程
}
}, "NotifyingThread");
waitingThread.start();
notifyingThread.start();
waitingThread.join();
notifyingThread.join();
}
/**
* wait()会释放锁
*/
public static void demonstrateWaitReleasesLock() throws InterruptedException {
System.out.println("\n=== wait()会释放锁 ===");
Object lock = new Object();
// 线程1:获取锁并等待
Thread thread1 = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("线程1:获得锁,开始等待...");
lock.wait(); // 释放锁并等待
System.out.println("线程1:被唤醒,重新获得锁");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}, "Thread-1");
// 线程2:获取同一个锁
Thread thread2 = new Thread(() -> {
try {
Thread.sleep(1000); // 确保线程1先等待
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
synchronized (lock) {
System.out.println("线程2:获得锁(线程1在等待中)");
try {
Thread.sleep(2000); // 持有锁2秒
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("线程2:唤醒线程1");
lock.notify();
System.out.println("线程2:释放锁");
}
}, "Thread-2");
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("观察:线程2能够获得锁,说明wait()释放了锁");
}
/**
* wait()必须在synchronized块中使用
*/
public static void demonstrateWaitRequiresSynchronized() {
System.out.println("\n=== wait()必须在synchronized块中使用 ===");
Object lock = new Object();
try {
// 错误:在synchronized块外调用wait()
lock.wait();
} catch (IllegalMonitorStateException e) {
System.out.println("错误:" + e.getClass().getSimpleName() + " - " + e.getMessage());
System.out.println("wait()必须在synchronized块中调用");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 正确用法
synchronized (lock) {
try {
System.out.println("正确:在synchronized块中调用wait()");
// lock.wait(); // 这里不实际调用,避免无限等待
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* wait()的不同重载方法
*/
public static void demonstrateWaitOverloads() throws InterruptedException {
System.out.println("\n=== wait()的重载方法 ===");
Object lock = new Object();
Thread timeoutWaitThread = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("开始带超时的等待(2秒)...");
lock.wait(2000); // 最多等待2秒
System.out.println("等待结束(可能是超时或被唤醒)");
} catch (InterruptedException e) {
System.out.println("等待被中断");
Thread.currentThread().interrupt();
}
}
}, "TimeoutWaitThread");
timeoutWaitThread.start();
timeoutWaitThread.join();
// 演示精确时间的wait
Thread preciseWaitThread = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("开始精确时间等待...");
lock.wait(1000, 500000); // 1秒 + 500000纳秒
System.out.println("精确时间等待结束");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}, "PreciseWaitThread");
preciseWaitThread.start();
preciseWaitThread.join();
}
public static void main(String[] args) throws InterruptedException {
demonstrateWaitBasics();
demonstrateWaitReleasesLock();
demonstrateWaitRequiresSynchronized();
demonstrateWaitOverloads();
}
}
🆚 详细对比
核心差异对比
public class WaitVsSleepComparison {
/**
* 对比表格展示
*/
public static void showComparisonTable() {
System.out.println("=== wait() vs sleep() 详细对比 ===");
System.out.println();
System.out.printf("%-20s %-30s %-30s%n", "特性", "sleep()", "wait()");
System.out.println("─".repeat(80));
System.out.printf("%-20s %-30s %-30s%n", "所属类", "Thread类的静态方法", "Object类的实例方法");
System.out.printf("%-20s %-30s %-30s%n", "锁的处理", "不释放锁", "释放锁");
System.out.printf("%-20s %-30s %-30s%n", "使用位置", "任何地方", "必须在synchronized块中");
System.out.printf("%-20s %-30s %-30s%n", "唤醒方式", "时间到或被中断", "notify/notifyAll或超时");
System.out.printf("%-20s %-30s %-30s%n", "主要用途", "暂停执行", "线程间通信");
System.out.printf("%-20s %-30s %-30s%n", "异常", "InterruptedException", "InterruptedException");
System.out.printf("%-20s %-30s %-30s%n", "参数", "时间(毫秒/纳秒)", "时间(毫秒/纳秒)或无参");
System.out.printf("%-20s %-30s %-30s%n", "典型场景", "延迟执行", "生产者消费者模式");
}
/**
* 锁处理差异的实际演示
*/
public static void demonstrateLockDifference() throws InterruptedException {
System.out.println("\n=== 锁处理差异演示 ===");
Object lock = new Object();
// 测试sleep()不释放锁
System.out.println("--- sleep()不释放锁 ---");
Thread sleepThread = new Thread(() -> {
synchronized (lock) {
System.out.println("Sleep线程:获得锁,开始睡眠1秒");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Sleep线程:睡眠结束,释放锁");
}
}, "SleepThread");
Thread competingThread1 = new Thread(() -> {
System.out.println("竞争线程1:尝试获取锁...");
synchronized (lock) {
System.out.println("竞争线程1:获得锁!");
}
}, "CompetingThread1");
sleepThread.start();
Thread.sleep(100); // 确保sleepThread先获得锁
competingThread1.start();
sleepThread.join();
competingThread1.join();
System.out.println();
// 测试wait()释放锁
System.out.println("--- wait()释放锁 ---");
Thread waitThread = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("Wait线程:获得锁,开始等待");
lock.wait(1000); // 等待1秒或被唤醒
System.out.println("Wait线程:等待结束");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}, "WaitThread");
Thread competingThread2 = new Thread(() -> {
try {
Thread.sleep(200); // 确保waitThread先等待
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
System.out.println("竞争线程2:尝试获取锁...");
synchronized (lock) {
System.out.println("竞争线程2:获得锁!(wait线程正在等待)");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}, "CompetingThread2");
waitThread.start();
competingThread2.start();
waitThread.join();
competingThread2.join();
}
/**
* 使用场景对比
*/
public static void demonstrateUsageScenarios() throws InterruptedException {
System.out.println("\n=== 使用场景对比 ===");
// sleep()的典型使用场景
System.out.println("--- sleep()典型场景:延迟执行 ---");
System.out.println("执行任务1");
Thread.sleep(1000); // 延迟1秒
System.out.println("执行任务2");
// wait()的典型使用场景:生产者消费者
System.out.println("\n--- wait()典型场景:生产者消费者 ---");
ProducerConsumerExample example = new ProducerConsumerExample();
Thread producer = new Thread(example::produce, "Producer");
Thread consumer = new Thread(example::consume, "Consumer");
producer.start();
consumer.start();
Thread.sleep(3000); // 运行3秒
example.stop();
producer.join();
consumer.join();
}
/**
* 简单的生产者消费者示例
*/
static class ProducerConsumerExample {
private final Object lock = new Object();
private int item = 0;
private boolean hasItem = false;
private volatile boolean running = true;
public void produce() {
while (running) {
synchronized (lock) {
while (hasItem && running) {
try {
System.out.println("生产者:等待消费者消费");
lock.wait(); // 等待消费者消费
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
if (running) {
item++;
hasItem = true;
System.out.println("生产者:生产了物品 " + item);
lock.notify(); // 通知消费者
}
}
try {
Thread.sleep(500); // 生产间隔
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
}
public void consume() {
while (running) {
synchronized (lock) {
while (!hasItem && running) {
try {
System.out.println("消费者:等待生产者生产");
lock.wait(); // 等待生产者生产
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
if (running && hasItem) {
System.out.println("消费者:消费了物品 " + item);
hasItem = false;
lock.notify(); // 通知生产者
}
}
try {
Thread.sleep(800); // 消费间隔
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
}
public void stop() {
running = false;
synchronized (lock) {
lock.notifyAll(); // 唤醒所有等待的线程
}
}
}
public static void main(String[] args) throws InterruptedException {
showComparisonTable();
demonstrateLockDifference();
demonstrateUsageScenarios();
}
}
🔄 notify()和notifyAll()
唤醒机制详解
public class NotifyMechanism {
/**
* notify() vs notifyAll() 的区别
*/
public static void demonstrateNotifyDifference() throws InterruptedException {
System.out.println("=== notify() vs notifyAll() ===");
Object lock = new Object();
// 创建多个等待线程
Thread[] waitingThreads = new Thread[3];
for (int i = 0; i < 3; i++) {
final int threadId = i;
waitingThreads[i] = new Thread(() -> {
synchronized (lock) {
try {
System.out.println("线程" + threadId + ":开始等待");
lock.wait();
System.out.println("线程" + threadId + ":被唤醒!");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}, "WaitingThread-" + i);
}
// 启动所有等待线程
for (Thread thread : waitingThreads) {
thread.start();
}
Thread.sleep(1000); // 确保所有线程都在等待
// 测试notify() - 只唤醒一个线程
System.out.println("\n使用notify()唤醒一个线程:");
synchronized (lock) {
lock.notify(); // 只唤醒一个线程
}
Thread.sleep(1000);
// 测试notifyAll() - 唤醒所有线程
System.out.println("\n使用notifyAll()唤醒所有剩余线程:");
synchronized (lock) {
lock.notifyAll(); // 唤醒所有等待的线程
}
// 等待所有线程完成
for (Thread thread : waitingThreads) {
thread.join();
}
}
/**
* 虚假唤醒问题演示
*/
public static void demonstrateSpuriousWakeup() throws InterruptedException {
System.out.println("\n=== 虚假唤醒问题 ===");
SpuriousWakeupExample example = new SpuriousWakeupExample();
// 创建消费者线程
Thread consumer1 = new Thread(example::wrongConsumer, "WrongConsumer");
Thread consumer2 = new Thread(example::correctConsumer, "CorrectConsumer");
// 创建生产者线程
Thread producer = new Thread(example::producer, "Producer");
consumer1.start();
consumer2.start();
Thread.sleep(100);
producer.start();
Thread.sleep(5000); // 运行5秒
example.stop();
consumer1.join();
consumer2.join();
producer.join();
}
/**
* 虚假唤醒示例类
*/
static class SpuriousWakeupExample {
private final Object lock = new Object();
private int items = 0;
private volatile boolean running = true;
// 错误的消费者实现(使用if)
public void wrongConsumer() {
while (running) {
synchronized (lock) {
if (items == 0) { // 错误:使用if
try {
System.out.println("错误消费者:等待物品");
lock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
if (items > 0) {
items--;
System.out.println("错误消费者:消费物品,剩余: " + items);
} else {
System.out.println("错误消费者:虚假唤醒,没有物品可消费!");
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
}
// 正确的消费者实现(使用while)
public void correctConsumer() {
while (running) {
synchronized (lock) {
while (items == 0 && running) { // 正确:使用while
try {
System.out.println("正确消费者:等待物品");
lock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
if (items > 0 && running) {
items--;
System.out.println("正确消费者:消费物品,剩余: " + items);
}
}
try {
Thread.sleep(1200);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
}
public void producer() {
while (running) {
synchronized (lock) {
items++;
System.out.println("生产者:生产物品,总数: " + items);
lock.notifyAll(); // 唤醒所有等待的消费者
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
}
public void stop() {
running = false;
synchronized (lock) {
lock.notifyAll();
}
}
}
public static void main(String[] args) throws InterruptedException {
demonstrateNotifyDifference();
demonstrateSpuriousWakeup();
}
}
💡 实际应用案例
生产者消费者模式完整实现
public class ProducerConsumerPattern {
/**
* 使用wait/notify实现的阻塞队列
*/
static class BlockingQueue<T> {
private final Object[] queue;
private final Object lock = new Object();
private int head = 0; // 队列头
private int tail = 0; // 队列尾
private int count = 0; // 当前元素数量
public BlockingQueue(int capacity) {
this.queue = new Object[capacity];
}
@SuppressWarnings("unchecked")
public T take() throws InterruptedException {
synchronized (lock) {
// 使用while防止虚假唤醒
while (count == 0) {
System.out.println(Thread.currentThread().getName() + ": 队列为空,等待...");
lock.wait(); // 等待生产者生产
}
T item = (T) queue[head];
queue[head] = null; // 避免内存泄漏
head = (head + 1) % queue.length;
count--;
System.out.println(Thread.currentThread().getName() + ": 取出元素,队列大小: " + count);
lock.notifyAll(); // 通知等待的生产者
return item;
}
}
public void put(T item) throws InterruptedException {
synchronized (lock) {
// 使用while防止虚假唤醒
while (count == queue.length) {
System.out.println(Thread.currentThread().getName() + ": 队列已满,等待...");
lock.wait(); // 等待消费者消费
}
queue[tail] = item;
tail = (tail + 1) % queue.length;
count++;
System.out.println(Thread.currentThread().getName() + ": 放入元素,队列大小: " + count);
lock.notifyAll(); // 通知等待的消费者
}
}
public int size() {
synchronized (lock) {
return count;
}
}
}
/**
* 演示生产者消费者模式
*/
public static void demonstrateProducerConsumer() throws InterruptedException {
System.out.println("=== 生产者消费者模式演示 ===");
BlockingQueue<String> queue = new BlockingQueue<>(3);
// 创建生产者
Thread producer1 = new Thread(() -> {
try {
for (int i = 0; i < 5; i++) {
String item = "Producer1-Item" + i;
queue.put(item);
Thread.sleep(500);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}, "Producer1");
Thread producer2 = new Thread(() -> {
try {
for (int i = 0; i < 3; i++) {
String item = "Producer2-Item" + i;
queue.put(item);
Thread.sleep(800);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}, "Producer2");
// 创建消费者
Thread consumer1 = new Thread(() -> {
try {
for (int i = 0; i < 4; i++) {
String item = queue.take();
System.out.println("Consumer1 消费: " + item);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}, "Consumer1");
Thread consumer2 = new Thread(() -> {
try {
for (int i = 0; i < 4; i++) {
String item = queue.take();
System.out.println("Consumer2 消费: " + item);
Thread.sleep(1200);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}, "Consumer2");
// 启动所有线程
producer1.start();
producer2.start();
consumer1.start();
consumer2.start();
// 等待所有线程完成
producer1.join();
producer2.join();
consumer1.join();
consumer2.join();
System.out.println("最终队列大小: " + queue.size());
}
public static void main(String[] args) throws InterruptedException {
demonstrateProducerConsumer();
}
}
📝 最佳实践
使用建议和注意事项
public class BestPractices {
/**
* wait()使用最佳实践
*/
public static void waitBestPractices() {
System.out.println("=== wait()最佳实践 ===");
System.out.println("1. 总是在while循环中使用wait()");
System.out.println(" while (condition) {");
System.out.println(" object.wait();");
System.out.println(" }");
System.out.println(" 原因:防止虚假唤醒");
System.out.println("\n2. 总是在synchronized块中使用wait()");
System.out.println(" synchronized (object) {");
System.out.println(" object.wait();");
System.out.println(" }");
System.out.println(" 原因:wait()需要持有对象的监视器锁");
System.out.println("\n3. 使用notifyAll()而不是notify()");
System.out.println(" object.notifyAll(); // 推荐");
System.out.println(" object.notify(); // 可能导致死锁");
System.out.println(" 原因:notify()可能唤醒错误的线程");
System.out.println("\n4. 处理InterruptedException");
System.out.println(" try {");
System.out.println(" object.wait();");
System.out.println(" } catch (InterruptedException e) {");
System.out.println(" Thread.currentThread().interrupt();");
System.out.println(" return; // 或其他适当的处理");
System.out.println(" }");
}
/**
* sleep()使用最佳实践
*/
public static void sleepBestPractices() {
System.out.println("\n=== sleep()最佳实践 ===");
System.out.println("1. 不要在synchronized块中使用长时间sleep()");
System.out.println(" synchronized (lock) {");
System.out.println(" Thread.sleep(10000); // 不好:长时间持有锁");
System.out.println(" }");
System.out.println("\n2. 处理InterruptedException");
System.out.println(" try {");
System.out.println(" Thread.sleep(1000);");
System.out.println(" } catch (InterruptedException e) {");
System.out.println(" Thread.currentThread().interrupt();");
System.out.println(" }");
System.out.println("\n3. 使用TimeUnit提高可读性");
System.out.println(" TimeUnit.SECONDS.sleep(5); // 更清晰");
System.out.println(" Thread.sleep(5000); // 不如上面清晰");
System.out.println("\n4. 考虑使用ScheduledExecutorService");
System.out.println(" 对于定时任务,推荐使用ScheduledExecutorService");
System.out.println(" 而不是Thread.sleep()");
}
/**
* 常见错误示例
*/
public static void commonMistakes() {
System.out.println("\n=== 常见错误 ===");
System.out.println("❌ 错误1:在if中使用wait()");
System.out.println("if (condition) { object.wait(); } // 可能虚假唤醒");
System.out.println("\n❌ 错误2:在synchronized块外使用wait()");
System.out.println("object.wait(); // 抛出IllegalMonitorStateException");
System.out.println("\n❌ 错误3:使用notify()而不是notifyAll()");
System.out.println("object.notify(); // 可能唤醒错误的线程");
System.out.println("\n❌ 错误4:混淆sleep()和wait()的用途");
System.out.println("Thread.sleep(1000); // 用于线程通信 - 错误");
System.out.println("object.wait(1000); // 用于简单延迟 - 错误");
System.out.println("\n❌ 错误5:不处理InterruptedException");
System.out.println("try { Thread.sleep(1000); }");
System.out.println("catch (InterruptedException e) {} // 忽略异常");
}
public static void main(String[] args) {
waitBestPractices();
sleepBestPractices();
commonMistakes();
}
}
📝 总结
🎯 核心要点
| 特性 | sleep() | wait() |
|---|---|---|
| 所属 | Thread类静态方法 | Object类实例方法 |
| 锁处理 | 不释放锁 | 释放锁 |
| 使用位置 | 任何地方 | synchronized块中 |
| 唤醒方式 | 时间到或中断 | notify/notifyAll |
| 主要用途 | 暂停执行 | 线程通信 |
| 典型场景 | 延迟、轮询 | 生产者消费者 |
💡 使用建议
-
sleep()适用场景:
-
简单的延迟执行
-
轮询等待某个条件
-
控制任务执行频率
-
-
wait()适用场景:
-
线程间协作通信
-
生产者消费者模式
-
条件等待
-
-
最佳实践:
-
wait()总是在while循环中使用
-
优先使用notifyAll()而不是notify()
-
正确处理InterruptedException
-
避免在synchronized块中长时间sleep()
-
⚠️ 注意事项
-
虚假唤醒:wait()可能在没有notify()的情况下被唤醒
-
IllegalMonitorStateException:wait()必须在synchronized块中
-
死锁风险:notify()可能唤醒错误的线程
-
中断处理:正确处理InterruptedException
🚀 进阶学习
-
学习java.util.concurrent包中的高级工具
-
了解Condition接口的使用
-
掌握CountDownLatch、Semaphore等同步工具
-
学习CompletableFuture异步编程
wait()和sleep()虽然都能让线程暂停,但它们的设计目的和使用场景完全不同。理解它们的区别是掌握Java并发编程的重要一步!
记住:sleep()是为了暂停执行,wait()是为了线程通信。选择正确的工具能让你的并发程序更加健壮。 实践建议:多写生产者消费者的例子,加深对wait/notify机制的理解。
更多推荐



所有评论(0)