在 Java 中,wait() 和 notify() 是用于线程间通信的重要方法。它们属于 Object 类,而不是 Thread 类,因为它们操作的是共享对象的监视器(monitor)。以下是它们的用法以及需要注意的事项。
基本概念
wait() 方法:
让当前线程进入等待状态,并释放它持有的对象锁。
必须在同步代码块或同步方法中调用,否则会抛出 IllegalMonitorStateException。
等待线程可以被其他线程通过 notify() 或 notifyAll() 唤醒。
notify() 方法:
唤醒一个正在等待该对象锁的线程。
如果有多个线程等待,具体唤醒哪一个线程由 JVM 决定。
notifyAll() 方法:
唤醒所有等待该对象锁的线程。
示例代码
生产者-消费者问题
下面是使用 wait() 和 notify() 实现的生产者-消费者模型。
class SharedResource {
private int data;
private boolean isProduced = false;
// 生产数据
public synchronized void produce(int value) throws InterruptedException {
while (isProduced) {
wait(); // 等待消费完毕
}
data = value;
System.out.println("Produced: " + value);
isProduced = true;
notify(); // 通知消费者
}
// 消费数据
public synchronized int consume() throws InterruptedException {
while (!isProduced) {
wait(); // 等待生产
}
System.out.println("Consumed: " + data);
isProduced = false;
notify(); // 通知生产者
return data;
}
}
public class ProducerConsumerDemo {
public static void main(String[] args) {
SharedResource resource = new SharedResource();
// 生产者线程
Thread producer = new Thread(() -> {
try {
for (int i = 0; i < 5; i++) {
resource.produce(i);
Thread.sleep(100); // 模拟生产延迟
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
// 消费者线程
Thread consumer = new Thread(() -> {
try {
for (int i = 0; i < 5; i++) {
resource.consume();
Thread.sleep(200); // 模拟消费延迟
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
producer.start();
consumer.start();
}
}
运行步骤
启动线程:生产者和消费者线程交替运行。
线程通信:生产者调用 wait() 等待消费者消费完毕;消费者调用 wait() 等待生产者生产数据。
锁和同步:synchronized 关键字确保了线程安全。
注意事项
wait() 和 notify() 必须在同步块中使用:
synchronized (obj) {
obj.wait();
}
否则会抛出 IllegalMonitorStateException。
释放锁:
调用 wait() 后,线程会释放锁,进入等待队列。
被 notify() 唤醒后,线程会尝试重新获取锁并继续执行。
死锁风险:
小心使用 wait() 和 notify(),避免逻辑错误导致死锁。
用 notifyAll() 替代 notify()(视情况而定):
如果多个线程在等待相同的对象,使用 notify() 可能会导致某些线程永远得不到唤醒。
notifyAll() 更加安全,但可能降低效率。
推荐替代方案
对于现代 Java 开发,可以使用更高级的并发工具,比如:
BlockingQueue:用于生产者-消费者模型。
Condition:提供类似 wait() 和 notify() 的功能,但更灵活。
CountDownLatch 和 Semaphore:适用于更复杂的线程间协调需求。
wait() 和 notify() 更接近底层,在简单场景中足够,但高并发场景下推荐使用 java.util.concurrent 提供的工具。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70040412/viewspace-3051216/
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70042566/viewspace-3054640/ ,如需转载,请注明出处,否则将追究法律责任。