wait() vs sleep() 在 Java 中:多线程的巅峰对决
\n\n想象一下,您是一位乐队指挥。您有小提琴手(线程),他们需要协调演奏,但有时他们需要等待其他人完成他们的部分。在 Java 中,有两种强大的工具可以管理此类暂停:wait() 和 sleep()。乍一看,它们很相似——两者都会使线程“暂停”一段时间。但实际上,它们是完全不同的机制,混淆它们肯定会造成死锁或竞态条件。
本文是您穿越多线程丛林指南。我们不仅会列出区别,还会通过生动的示例进行剖析,让您永远记住:sleep 是暂停,而 wait 是释放资源。开始吧!
\n\n什么是 sleep()?(Thread.sleep)
\n\nThread.sleep(毫秒) 方法是将当前线程“休眠”指定时间的最简单方法。线程只是休息,不会释放对象的锁。它就像一只懒惰的猫,在沙发上打盹,但仍然用爪子抓着玩具。
关于 sleep() 的重要事实:
- \n
- 它是
Thread类的静态方法。 \n - 线程不会释放它持有的监视器(锁)。 \n
- 计时器到期后,线程进入 Runnable(可运行)状态。 \n
- 可能抛出
InterruptedException。 \n
简单示例:
\npublic class SleepExample {\n public static void main(String[] args) throws InterruptedException {\n System.out.println("开始: " + System.currentTimeMillis());\n Thread.sleep(2000); // 休眠 2 秒\n System.out.println("醒来: " + System.currentTimeMillis());\n }\n}\n\n结果:两次输出之间恰好间隔 2 秒。线程只是等待,什么也不做。
\n\n什么是 wait()?(Object.wait)
\n\nwait() 方法不仅仅是一个暂停,而是一种线程间通信机制。它定义在 Object 类中,并且只能在同步块(synchronized)内调用。当线程调用 wait() 时,它会:
- \n
- 释放对象的监视器(即释放锁)。 \n
- 进入 WAITING 或 TIMED_WAITING 状态(如果指定了超时时间)。 \n
- 等待,直到另一个线程在同一个对象上调用
notify()或notifyAll()。 \n
这就像您说:“我放下叉子,等待第二道菜上桌。”您不仅仅是睡觉——您是在为其他人腾出桌边的位置。
\n\n基本示例:
\npublic class WaitNotifyExample {\n private static final Object lock = new Object();\n\n public static void main(String[] args) throws InterruptedException {\n Thread waiter = new Thread(() -> {\n synchronized (lock) {\n try {\n System.out.println("服务员线程正在等待...");\n lock.wait(); // 释放 lock 并等待\n System.out.println("服务员线程收到通知!");\n } catch (InterruptedException e) {\n Thread.currentThread().interrupt();\n }\n }\n });\n\n Thread notifier = new Thread(() -> {\n synchronized (lock) {\n System.out.println("厨师线程正在准备...");\n try {\n Thread.sleep(1000); // 模拟烹饪\n } catch (InterruptedException e) {\n Thread.currentThread().interrupt();\n }\n lock.notify(); // 唤醒等待的线程\n System.out.println("厨师已通知服务员!");\n }\n });\n\n waite