【从零开始学Java | 第四十二篇】生产者消费者问题(等待唤醒机制)
目录前言一、什么是“生产者-消费者”模型1.经典实现wait()、notifyAll()2.阻塞队列实现BlockingQueue①阻塞队列的继承结构总结前言之前学习多线程所执行的代码我们可以看到他们的执行都是随机的哪个电影院窗口卖出一张门票是不固定的但是如果我们想要让线程执行的顺序固定应该如何操作呢一、什么是“生产者-消费者”模型为了方便理解我们打个最通俗的比方包子铺。生产者Producer后厨做包子的师傅。消费者Consumer在前台买包子的顾客。缓冲区Buffer装包子的蒸笼容量有限比如最多装 10 个。如果没有蒸笼师傅做好一个包子必须亲手交到顾客手里才能回去做下一个。如果顾客还没来师傅就只能傻等着反过来如果师傅做得慢顾客也得干等着。1.经典实现wait()、notifyAll()桌子定义了锁、消费者可以消费的总数、判断桌子上是否有包子。public class Desk { //锁 public static Object obj new Object(); //总数 public static int count 10; //flag判空 public static int flag 0; }消费者线程//消费者线程 public class Consumer extends Thread{ Override public void run() { while(true){ synchronized (Desk.obj){ if(Desk.count 0){ //1.消费者吃饱了 break; } else { //2.消费者没吃饱 if(Desk.flag 0){ //2.1桌子上没食物 try { Desk.obj.wait(); //2.1.1等待 } catch (InterruptedException e) { throw new RuntimeException(e); } } else { //2.2桌子上有食物 Desk.count--; //2.2.1开吃 Desk.flag 0; System.out.println(getName() 正在吃东西还能再吃 Desk.count 份食物); Desk.obj.notifyAll(); //2.2.2叫醒生产者. } } } } } }生产者线程//生产者线程 public class Productor extends Thread{ Override public void run() { while(true){ synchronized (Desk.obj){ if(Desk.count 0){ //1.消费者吃饱了就不用做了 break; } else { //2.消费者没吃饱 if(Desk.flag 1){ //2.1桌子上是有食物的 try { Desk.obj.wait(); } catch (InterruptedException e) { throw new RuntimeException(e); } } else{ //2.2桌子上没食物 Desk.flag 1; //2.2.1做食物 System.out.println(getName() 正在做食物); Desk.obj.notifyAll(); } } } } } }测试public class Test { public static void main(String[] args) { Consumer c new Consumer(); Productor p new Productor(); c.setName(消费者); p.setName(生产者); c.start(); p.start(); } }运行结果2.阻塞队列实现BlockingQueue①阻塞队列的继承结构接口Itreable、Collection、Queue、BlockingQueue实现类ArrayBlockingQueue底层是数组有界。LinkedBlockingQueue底层是链表无界但不是真正的无界最大为int的最大值。消费者线程public class Consumer extends Thread{ ArrayBlockingQueueString queue; public Consumer(ArrayBlockingQueueString queue) { this.queue queue; } Override public void run() { while(true){ try { String take queue.take(); } catch (InterruptedException e) { throw new RuntimeException(e); } } } }生产者线程public class Productor extends Thread{ ArrayBlockingQueueString queue; public Productor(ArrayBlockingQueueString queue) { this.queue queue; } Override public void run() { try { queue.put(包子); } catch (InterruptedException e) { throw new RuntimeException(e); } } }测试public class Test { public static void main(String[] args) { //定义阻塞队列 ArrayBlockingQueueString abq new ArrayBlockingQueue(1); Consumer c new Consumer(abq); Productor p new Productor(abq); c.start(); p.start(); } }总结生产者-消费者模型并不是一个具体的类而是一种极具智慧的架构思想。解耦生产者和消费者彼此不直接打交道只和缓冲区交互。异步大家各干各的互不干扰。缓冲完美解决生产和消费速度不匹配的问题。