在Java中,wait()
和yield()
都是用于线程控制的方法,但它们的作用和使用场景完全不同。以下是它们的详细区别:
1. wait()
方法
(1) 定义
wait()
是Object
类的方法,用于线程间通信。
- 调用
wait()
的线程会释放锁并进入等待状态,直到其他线程调用notify()
或notifyAll()
唤醒它,或者等待超时。
(2) 使用场景
- 用于多线程协作,通常与
notify()
或notifyAll()
配合使用。
- 常用于生产者-消费者模型或线程间的条件等待。
(3) 特点
- 释放锁:调用
wait()
的线程会释放持有的锁。
- 需要同步块:
wait()
必须在synchronized
块或方法中调用,否则会抛出IllegalMonitorStateException
。
- 唤醒机制:线程可以通过
notify()
、notifyAll()
或超时唤醒。
(4) 示例
1 2 3 4 5 6
| synchronized (lock) { while (conditionNotMet) { lock.wait(); } }
|
2. yield()
方法
(1) 定义
yield()
是Thread
类的静态方法,用于提示线程调度器当前线程愿意让出CPU资源。
- 调用
yield()
的线程会从运行状态进入就绪状态,让其他线程有机会执行。
(2) 使用场景
- 用于线程调度的优化,避免某个线程长时间占用CPU。
- 通常用于测试或调试,实际开发中较少使用。
(3) 特点
- 不释放锁:调用
yield()
的线程不会释放持有的锁。
- 不保证让出CPU:
yield()
只是一个提示,具体是否让出CPU由线程调度器决定。
- 不进入阻塞状态:线程从运行状态进入就绪状态,而不是阻塞状态。
(4) 示例
1 2 3 4 5 6
| public void run() { for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + " - " + i); Thread.yield(); } }
|
3. wait()
和yield()
的区别
特性 |
wait() |
yield() |
所属类 |
Object 类 |
Thread 类 |
作用 |
线程等待,释放锁 |
线程让出CPU,不释放锁 |
锁的释放 |
释放锁 |
不释放锁 |
调用位置 |
必须在synchronized 块或方法中调用 |
可以在任何地方调用 |
线程状态 |
从运行状态进入等待状态(WAITING) |
从运行状态进入就绪状态(RUNNABLE) |
唤醒机制 |
需要notify() 、notifyAll() 或超时唤醒 |
无需唤醒,由线程调度器决定 |
使用场景 |
线程间通信,条件等待 |
线程调度优化,避免长时间占用CPU |
是否抛出异常 |
可能抛出InterruptedException |
不会抛出异常 |
4. 使用注意事项
(1) wait()
的注意事项
- 必须在
synchronized
块或方法中调用。
- 通常与
while
循环结合使用,避免虚假唤醒(Spurious Wakeup)。
- 调用
wait()
后,线程会释放锁,其他线程可以进入同步块。
(2) yield()
的注意事项
yield()
只是一个提示,具体是否让出CPU由线程调度器决定。
- 不能依赖
yield()
来控制线程执行的顺序。
- 在实际开发中,
yield()
的使用场景较少,通常用于调试或测试。
5. 示例对比
(1) wait()
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class SharedResource { private boolean ready = false;
public synchronized void produce() { ready = true; notify(); }
public synchronized void consume() throws InterruptedException { while (!ready) { wait(); } System.out.println("Consumed"); } }
|
(2) yield()
示例
1 2 3 4 5 6 7 8 9
| class Worker implements Runnable { @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + " - " + i); Thread.yield(); } } }
|
总结
wait()
:用于线程间通信,释放锁并等待条件满足,通常与notify()
或notifyAll()
配合使用。
yield()
:用于线程调度优化,提示让出CPU,但不释放锁,实际开发中较少使用。
理解wait()
和yield()
的区别及其适用场景,有助于更好地编写多线程程序。