Java的wait和yield区别

在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()的线程不会释放持有的锁。
  • 不保证让出CPUyield()只是一个提示,具体是否让出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(); // 提示让出CPU
}
}

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(); // 提示让出CPU
}
}
}

总结

  • wait():用于线程间通信,释放锁并等待条件满足,通常与notify()notifyAll()配合使用。
  • yield():用于线程调度优化,提示让出CPU,但不释放锁,实际开发中较少使用。

理解wait()yield()的区别及其适用场景,有助于更好地编写多线程程序。