生产者消费者模式是一种常见的设计模式,掌握一种完美,稳定的实现方式非常有用,下面我就使用misa管程实现生产者消费者模式。
这种实现的优点:
1.稳定,不会出现死锁现象
2.运行速度相对较快
话不多说,直接上代码:
管程类:
package com.brave.test; import java.util.ArrayList; import java.util.List; /** * * @描述:管程区 * * @author <p>1286998496@qq.com<p> brave * * @date 2017-9-18 */ public class Monitor { /** * 互斥量,集合内的成品数量 */ private static int mutex = 0; /** * 缓冲区边界 */ private static int N = 20; /** * 缓冲区 */ private static List<String> stuffArr = new ArrayList<String>(N); /** * * @描述:往缓冲区内存放数据(生产) * * @author <p>1286998496@qq.com<p> brave * * @date 2017-9-18 * * @param stuff * @throws InterruptedException */ public synchronized void insert(String stuff) throws InterruptedException{ /** * 循环验证,当线程被唤醒后,重新检测条件是否成立 */ while(mutex == N){ System.out.println("缓冲区已满,唤醒消费者"); notifyAll(); wait(); System.out.println("==生产者被唤醒=="); } stuffArr.add(stuff); //互斥量加一 mutex++; //缓冲区有数据后唤醒消费者 if(mutex == 1)notifyAll(); } /** * * @描述:移除缓冲区内数据(消费) * * @author <p>1286998496@qq.com<p> brave * * @date 2017-9-18 * * @return * @throws InterruptedException */ public synchronized String remove() throws InterruptedException{ String result = null; while(mutex == 0){ System.out.println("缓冲区已空,唤醒生产者"); notifyAll(); wait(); System.out.println("==消费者被唤醒=="); } result = stuffArr.remove(0); mutex--; if(mutex == N-1)notifyAll(); return result; } }
生产者:
package com.brave.test; public class Producers implements Runnable { private Monitor monitor = null; public Producers(Monitor monitor) { this.monitor = monitor; } @Override public void run() { int num = 1; while(true){ System.out.println("开始生产商品"); try { Thread.sleep(1000); System.out.println("商品生产完成:第【" + num + "】件商品"); monitor.insert("第【" + num++ + "】件商品"); } catch (InterruptedException e) { e.printStackTrace(); } } } }
消费者:
package com.brave.test; public class Consumers implements Runnable { private Monitor monitor = null; private String name = null; public Consumers(String name ,Monitor monitor) { this.monitor = monitor; this.name = name; } @Override public void run() { while(true){ System.out.println("开始消费商品"); try { System.out.println(name + "-->商品消费完成:" + monitor.remove() ); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
测试类:
package com.brave.test; public class Test { public static void main(String[] args) { Monitor monitor = new Monitor(); Thread consumers1 = new Thread(new Consumers("一号消费者",monitor)); Thread consumers2 = new Thread(new Consumers("二号消费者",monitor)); Thread producers = new Thread(new Producers(monitor)); producers.start(); consumers1.start(); consumers2.start(); } }
需要注意的是,在测试方法里,每个线程要使用同一个实例。