juc包中BlockingQueue的生產者消費者示例
阿新 • • 發佈:2019-02-08
/*
*Usage example, based on a typical producer-consumer scenario.
*Note that a <tt>BlockingQueue</tt> can safely be used with multiple
*producers and multiple consumers.
<pre name="code" class="java">*/
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(); }}
撇開其鎖的具體實現,其流程就是我們在作業系統課上學習到的標準生產者模式,看來那些枯燥的理論還是有用武之地的。其中,最核心的還是Java的鎖實現,有興趣的朋友可以再進一步深究一下
LinkedBlockingQueue的具體實現
public void put(E e) throws InterruptedException { if (e == null) throw new NullPointerException(); int c = -1; final ReentrantLock putLock = this.putLock; final AtomicInteger count = this.count; putLock.lockInterruptibly(); try { try { while (count.get() == capacity) notFull.await(); } catch (InterruptedException ie) { notFull.signal(); // propagate to a non-interrupted thread throw ie; } insert(e); c = count.getAndIncrement(); if (c + 1 < capacity) notFull.signal(); } finally { putLock.unlock(); } if (c == 0) signalNotEmpty(); }