🍄 博客搬家:第一版发布于 2016/04/15 20:31java
🌺 原博客地址:https://my.oschina.net/sunqinwen/blog/660881设计模式
本实例中单独为生产者和消费者各开辟一个线程做为生产者和消费者的执行线程,在生产者消费者设计模式中存在一个数据缓冲区,使生产者和消费者的“生产”和“消费”动做都在该缓冲区进行,这样作的目的就是保证了生产者和消费者的完美解耦,试想一下若是没了这个缓冲区,生产者和消费者中的方法互调,那么两个类的关联度(耦合度)就会很高,一旦一个发生变化,势必会影响另一个;ide
下面开始咱们的实例:this
首先是生产者的代码:spa
/** * 生产者 */ public class Product implements Runnable{ private Queue queue; public Product(Queue queue){ this.queue = queue; } @Override public void run() { try{ for(int i = 0; i < 10; i++){ queue.product("Product------" + "No." + i);//开始生产 } }catch (Exception e){ e.printStackTrace(); } } }
这是消费者:.net
/** * 消费者 */ public class Consumer implements Runnable{ private Queue queue; public Consumer(Queue queue){ this.queue = queue; } @Override public void run() { try{ for(int i = 0; i < 10; i++){ System.out.println("already gone : " + queue.consumer());//开始消费 } }catch (Exception e){ e.printStackTrace(); } } }
这是缓冲区,几乎全部的逻辑都是在这里实现的:线程
/** * 队列缓冲区 */ public class Queue { private Object signal = new Object();//当前线程的挂起和执行标记 private boolean isFull = false;//队列是否已满 private List list = new ArrayList<>();//队列 public void product(String msg) throws Exception{ synchronized (signal){ if(!isFull){//若是没有满,执行以下代码 list.add(msg);//加进队列 isFull = true; System.out.println("Product One !"); signal.notify();//唤醒当前消费者里面被挂起的线程 } signal.wait();//不然,若是当前满了,说明消费者正在消费,挂起当前生产线程 } } public String consumer() throws Exception{ synchronized (signal){ if(!isFull){ //不满,说明生产者正在生产,应当挂起consumer线程 System.out.println("Empty Product !"); signal.wait(); } isFull = false;//已消费,队列被标记为不满状态 signal.notify();//通知生产者 } //消费(读取) String result = ""; if(list.size() > 0){ result = this.list.get(list.size() - 1); this.list.remove(list.size() - 1); } return result; } }
上面这个模式利用java现有的阻塞队列很容易实现,能够避免上述代码中很大一部分代码(线程的挂起、唤醒、队列弹出数据等)设计