当仓库满了时才允许消费者消费,当仓库为空时,才允许生产者生产
生产者类
package com.goodwe.entity; import java.util.Queue; /** * @Author : Wang Huyun * @Creation time : 2019/5/21 15:06 * @Title:生产者 */ public class Producer implements Runnable { private Queue<String> queue; private final int maxSize; public Producer(Queue<String> queue, int maxSize) { this.queue = queue; this.maxSize = maxSize; } @Override public void run() { produce(); } void produce() { try { synchronized (queue) { while (true) { if (queue.size() == maxSize) { System.out.println("仓库已满,等待消费者消费!"); queue.wait(); } queue.add("产品"); Thread.sleep(1000); System.out.println("生产者正在生产"); queue.notifyAll(); } } } catch (InterruptedException e) { e.printStackTrace(); } } }
消费者类
package com.goodwe.entity; import java.util.Queue; /** * @Author : Wang Huyun * @Creation time : 2019/5/21 15:17 * @Title:消费者 */ public class Consumer implements Runnable { private Queue<String> queue; public Consumer(Queue<String> queue) { this.queue = queue; } @Override public void run() { consume(); } void consume() { try { synchronized (queue) { while (true) { if (queue.isEmpty()) { System.out.println("仓库已空,等待生产者生产!"); queue.wait(); continue; } queue.remove(); System.out.println("消费者正在消费"); queue.notifyAll(); Thread.sleep(1000); } } } catch (InterruptedException e) { e.printStackTrace(); } } }
主函数
package com.goodwe; import com.goodwe.entity.Consumer; import com.goodwe.entity.Producer; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); int maxSize = 5; Thread producer = new Thread(new Producer(queue, maxSize)); Thread consumer = new Thread(new Consumer(queue)); producer.start(); consumer.start(); } }
总结
作为生产者,当队列满时调用了队列的wait()方法,表示等待,并且此时释放了锁。作为消费者此时获取到锁并且移除队首元素时调用了notifyAll()方法,此时生产者由wait等待状态转换为唤醒状态,但注意!此时仅仅是线程被唤醒了,有了争夺CPU资源的资格,并不代表下一步就一定是生产者生产,还有可能消费者继续争夺了CPU资源。一定记住是被唤醒了,有资格争夺CPU资源。notifyAll()表示的是唤醒所有等待的线程,所有等待的线程被唤醒过后,都有了争夺CPU资源的权利,至于是谁会获得这个锁,那不一定。而如果是使用notify(),那就代表唤醒所有等待线程中的一个,只是一个被唤醒具有了争夺CPU的权力,其他没被唤醒的线程继续等待。如果等待线程就只有一个那么notify()和notifyAll()就没区别,不止一个那区别就大了,一个是只唤醒其中一个,一个是唤醒所有。唤醒不是代表这个线程就一定获得CPU资源一定获得锁,而是有了争夺的权利。