本文共 4141 字,大约阅读时间需要 13 分钟。
什么是生产者消费者模式?
生产者消费者模式并不是23中设计模式中的一种,在面向对象编程中我们前人总结了一些比较好的设计模式,就像23种设计模式一样。但是面向过程编程的时候,我们前人也给我们总结了一些好的设计模式,比如今天我们要了解到的生产者-消费者模式。
在我们日常升生活中,常常会见到这样一种场景,比如我们取麦当劳买东西,当我们点完之后,会在一旁等待着我们的餐,然后做好了服务员就会通知我们取拿餐,这样一种简单的模式就是典型的生产者-消费者模式。
在我们多线程中要实现线程之间的通信(线程协作),就需要用到生产者-消费者模式
解决线程通信有两种方式:1.管程法 2.信号灯法1.管程法
今天我们重点学习一下管程法,管程法主要以下几个要素:我们来看下代码实现:
/** * 线程通信-管程法 */public class ThreadPcOfTubeMethod { public static void main(String[] args) { SynchronizeContainer container = new SynchronizeContainer(); new Product(container).start(); new Consumers(container).start(); }}//1.生产者class Product extends Thread{ SynchronizeContainer container; public Product(SynchronizeContainer container) { this.container = container; } @Override public void run() { //生产 for (int i = 0; i < 100; i++) { System.out.println("生产----->第"+i+"个面包"); container.push(new Bread(i)); } }}//2.消费者class Consumers extends Thread{ SynchronizeContainer container; public Consumers(SynchronizeContainer container) { this.container = container; } @Override public void run() { //消费 for (int i = 0; i < 100; i++) { System.out.println("消费----->第"+container.pop().id+"个面包"); } }}//3.并发容器(缓冲区):// 1.存:容器不够了,不能存了,等待消费// 2.取:容器为空容器,等待生产class SynchronizeContainer{ Bread[] breads = new Bread[10]; int count = 0;//计数器 //生产----存储 public synchronized void push(Bread bread){ //容器存在空间可以生产 //不能生产 if(count==breads.length){ try { this.wait();//线程阻塞,消费者通知生产,阻塞解除 } catch (InterruptedException e) { e.printStackTrace(); } } breads[count] = bread; count++; this.notifyAll();//存在数据了,通知消费 } //消费----获取 public synchronized Bread pop(){ //如果容器中有数据,可以消费。 //如果没有数据,等待 if (count==0){ try { this.wait();//线程阻塞,生产者通知消费解除阻塞 } catch (InterruptedException e) { e.printStackTrace(); } } //从最后一个位置拿 count--; Bread bread =breads[count]; this.notifyAll();//存在空间了,可以唤醒生产者生产了 return bread; }}//4.商品(面包)class Bread{ int id; public Bread(int id) { this.id = id; }}
2.信号灯法
我们简单的了解一下信号灯法,信号灯法是通过标志位来实现的。举一个演员表演,观众看的例子:/** * 协作模型:生产者消费者实现方式二-信号灯法 * 思想:借助标志位 */public class ThreadPcOfSignalLight { public static void main(String[] args) { Tv tv = new Tv(); new Players(tv).start(); new Watchers(tv).start(); }}//生产者:演员class Players extends Thread{ Tv tv; public Players(Tv tv){ this.tv=tv; } @Override public void run() { for (int i = 0; i < 20; i++) { if (i%2==0){ this.tv.play("天龙八部"); }else { this.tv.play("广告:天才第一步,雀氏纸尿裤"); } } }}//消费者:观众class Watchers extends Thread{ Tv tv; public Watchers(Tv tv){ this.tv=tv; } @Override public void run() { for (int i = 0; i < 20; i++) { tv.watch(); } }}//同一个资源:电视class Tv{ String voice; //信号灯,如果为真,表示观众等待 //信号灯,如果为假,表示演员等待 boolean flag = true; //表演 public synchronized void play(String voice){ //演员等待 if (!flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("演员表演了:"+voice); this.voice=voice; //唤醒 this.notifyAll(); //切换信号灯的状态 this.flag=!this.flag; } //观看 public synchronized void watch(){ //观众等待 if (flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("观众听到了:"+voice); //唤醒 this.notifyAll(); //切换信号灯的状态 this.flag=!this.flag; }}
转载地址:http://baiwi.baihongyu.com/