Java实现生产者--消费者问题

来源:互联网 发布:ubuntu12.04安装mysql 编辑:程序博客网 时间:2024/06/05 19:55

生产者–消费者问题在面试中经常会碰到,最近在看BlockingQueue的时候发现Java已经给了一个生产者–消费者的example

 class Producer implements Runnable {   private final BlockingQueue queue;    Producer(BlockingQueue q) { queue = q; }    public void run() {      try {        while (true) { queue.put(produce()); }      } catch (InterruptedException ex) { ... handle ...}    }    Object produce() { ... }  }  class Consumer implements Runnable {    private final BlockingQueue queue;    Consumer(BlockingQueue q) { queue = q; }    public void run() {      try {        while (true) { consume(queue.take()); }      } catch (InterruptedException ex) { ... handle ...}    }    void consume(Object x) { ... }  }  class Setup {    void main() {      BlockingQueue q = new SomeQueueImplementation();      Producer p = new Producer(q);      Consumer c1 = new Consumer(q);      Consumer c2 = new Consumer(q);      new Thread(p).start();      new Thread(c1).start();      new Thread(c2).start();    }  }

其中BlockingQueue的实现类有ArrayBlockingQueueLinkedBlockingQueuePriorityBlockingQueueSynchronousQueueSynchronousQueue实际上不是一个真正的队列,因为它不会为队列中元素维护存储空间,它维护的是一组线程。

阻塞队列提供了可阻塞的put和take方法,以及支持定时的offer和poll方法,如果队列已经满了,那么put方法将阻塞直到有空间可用,如果队列为空,那么take方法将阻塞直到元素可用。队列可以是有界的也可以无界的,无界队列永远都不会充满,因此无界队列上的put方法也永远不会阻塞。

在基于阻塞队列构建的生产者—消费者设计中,当数据生成时,生产者把数据放入到队列中,而当消费者准备处理数据时,将从队列中获取数据。生产者不需要知道消费者的数量或标识,或者它们是否是唯一的生产者,只需将数据放入队列即可。同样,消费者也不需要知道生产者是谁,或者工作来自于何处。

如果生产者生成工作的速率比消费者处理工作的速率快,那么工作项会在队列中累积起来,最终耗尽内存。如果使用有界队列,那么当队列充满时,生产者将阻塞并且不能继续生成工作,而消费这就有时间来赶上工作处理进度。

阻塞队列同样提供了一个offer方法,如果数据项不能被添加到队列中,那么返回失败状态。

0 0
原创粉丝点击