如何在 Java 中正确使用 wait, notify 和 notifyAll?

时间:2023-03-09 18:49:20
如何在 Java 中正确使用 wait, notify 和 notifyAll?

简介

    wait,notify,notifyAll,都是属于object对象提供的方法,但在实际工作中怎么使用这几个方法,确是很多程序员清楚,不够明白,在群里问,有人说,哪个线程想wait,就用

 需等待线程.wait(),就跟Thread.sleep()一样,唤醒也一样,这样显然是不对的。

   在 Java 中可以用 wait、notify 和 notifyAll 来实现线程间的通信。。举个例子,如果你的Java程序中有两个线程——即生产者和消费者,那么生产者可以通知消费者,让消费者开始消耗数据,因为队列缓 冲区中有内容待消费(不为空)。相应的,消费者可以通知生产者可以开始生成更多的数据,因为当它消耗掉某些数据后缓冲区不再为满。

 1、废话不多说,直接看demo吧

package hello.wait_notify;

import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ConcurrentLinkedQueue; /**
* Created by jacky on 2017/3/25 0025.
*/
public class Waint_Notify { public static void main(String args[])
{
ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue();
int maxSize = 10;
Thread producer = new Producer(queue, maxSize, "PRODUCER");
Thread consumer = new Consumer(queue, maxSize, "CONSUMER");
producer.start();
consumer.start(); } static class Producer extends Thread {
private ConcurrentLinkedQueue queue;
private int maxSize; public Producer(ConcurrentLinkedQueue queue, int maxSize, String name) {
super(name);
this.queue = queue;
this.maxSize = maxSize;
} @Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.size() == maxSize) {
try {
System.out.println("队列中已经满了,等待消费者消费!");
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
Random random = new Random();
int i = random.nextInt();
System.out.println("Producing value : " + i);
queue.add(i);
queue.notifyAll();
}
}
}
} static class Consumer extends Thread {
private ConcurrentLinkedQueue queue;
private int maxSize; public Consumer(ConcurrentLinkedQueue queue, int maxSize, String name) {
super(name);
this.queue = queue;
this.maxSize = maxSize;
} @Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.isEmpty()) {
System.out.println("队列已经空了,等待生产者放数据" );
try {
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
System.out.println("Consuming value : " + queue.remove());
queue.notifyAll();
}
}
}
}
}

2、结果

如何在 Java 中正确使用 wait, notify 和 notifyAll?

3、总结

1. 你可以使用wait和notify函数来实现线程间通信。你可以用它们来实现多线程(>3)之间的通信。

2. 永远在synchronized的函数里使用wait、notify和notifyAll,不然Java虚拟机会生成 IllegalMonitorStateException。

3. 永远在while循环里而不是if语句下使用wait。这样,循环会在线程睡眠前后都检查wait的条件,并在条件实际上并未改变的情况下处理唤醒通知。

4. 永远在多线程间共享的对象(在生产者消费者模型里即缓冲区队列)上使用wait。

5. 基于前文提及的理由,更倾向用 notifyAll(),而不是 notify()。