wait、notify应用场景(生产者-消费者模式)
Java实现生产者消费者的方式有:wait && notify、BlockingQueue、Lock && Condition等
wait、notify注意事项:
(1)可以使用wait()和notify()方法在Java中实现线程间通信。不只是一个或两个线程,而是多个线程可以使用这些方法相互通信。
(2)在synchronized方法或synchronized块中调用wait(),notify()和notifyAll()方法,否则JVM将抛出IllegalMonitorStateException。
(3)从while(条件)循环调用wait和notify方法,而不是从if()块调用,因为要重复检查条件,而不仅仅是一次。
(4)多使用notifyAll方法而不是notify。
下面是wait、notify等待通知实现的生产者-消费者模式:
生产者:
/** * 生产者 * * @author monkjavaer * @date 2018/12/15 11:13 */ public class Producer implements Runnable { /** * 产品容器 */ private final List<Integer> container; public Producer(List<Integer> container) { this.container = container; } /** * 生产者生产方法 * * @throws InterruptedException */ private void produce() throws InterruptedException { //产品容器容量 int capacity = 5; synchronized (container) { //当容器已满,暂停生产 while (container.size() == capacity) { System.out.println("...容器已经满了,暂停生产..."); container.wait(); } Random random = new Random(); int p = random.nextInt(50); //模拟1秒生产一个产品 TimeUnit.MILLISECONDS.sleep(1000); System.out.println("生产产品:" + p); container.add(p); container.notifyAll(); } } @Override public void run() { while (true) { try { produce(); } catch (InterruptedException e) { e.printStackTrace(); System.out.println("produce error"); } } } }
消费者:
/** * 消费者 * @author monkjavaer * @date 2018/12/15 11:13 */ public class Consumer implements Runnable{ /** * 产品容器 */ private final List<Integer> container; public Consumer(List<Integer> container) { this.container = container; } /** * 消费者消费产品 */ private void consume() throws InterruptedException { synchronized (container){ while (container.isEmpty()){ System.out.println("...容器是空的,暂停消费..."); container.wait(); } Integer p = container.remove(0); //模拟1秒消费一个产品 TimeUnit.MILLISECONDS.sleep(1000); System.out.println("消费产品:" + p); container.notifyAll(); } } @Override public void run() { while (true){ try { consume(); } catch (InterruptedException e) { e.printStackTrace(); System.out.println("consume error"); } } } }
测试:
public class ProducerConsumerTest { public static void main(String[] args) { List<Integer> container = new ArrayList<>(); Thread producer = new Thread(new Producer(container)); Thread consumer = new Thread(new Consumer(container)); producer.start(); consumer.start(); } }
输出:
生产产品:14 生产产品:17 消费产品:14 生产产品:0 生产产品:39 生产产品:4 生产产品:3 ...容器已经满了,暂停生产... 消费产品:17 消费产品:0 消费产品:39 消费产品:4 消费产品:3 ...容器是空的,暂停消费... 生产产品:25 生产产品:33 生产产品:17 消费产品:25 消费产品:33 消费产品:17 ...容器是空的,暂停消费...