■ Producer-Consumer パターン(生産者-消費者パターン)
* Queue(キュー)を用意し、 1つのプロセス(producer)が、データが生産できたらそのキューに追加。 もう1つのプロセス(consumer)が、キューからデータを取り出し、処理をする。 * キューは複数スレッドであるから、キューはスレッドセーフにする必要がある * キューが空の場合、consumerはproducerがデータを生成するのを待つ * キューが満杯の場合、producerはconsumerがデータを消費するのを待つ
■ サンプル
http://www.hyuki.com/dp/dpinfo.html#ProducerConsumerを参考に、Producer-Consumer パターンを理解するためのプログラムを組む。 (実際には、BlockingQueueを使った方がいいらしいので、あくまで理解のため) * producer = Customer(お客さん) * consumer = SE(システム・エンジニア)
SampleQueue.java
import java.util.Random; public class SampleQueue { private String targetJobInQueue = null; synchronized void order(String job) throws InterruptedException { while (this.targetJobInQueue != null) { System.out.println( Thread.currentThread().getName() + " waits (order)"); wait(); } System.out.println(Thread.currentThread().getName() + " order " + job); this.targetJobInQueue = job; this.doHeavyJob(); System.out.println(this.targetJobInQueue + " is in the Queue."); notifyAll(); } synchronized String work() throws InterruptedException { while (targetJobInQueue == null) { System.out.println( Thread.currentThread().getName() + " waits (work)"); wait(); } String job = this.targetJobInQueue; System.out.println(Thread.currentThread().getName() + " use " + job); this.targetJobInQueue = null; this.doHeavyJob(); System.out.println("There is no job in the Queue."); notifyAll(); return job; } private void doHeavyJob() throws InterruptedException { Random random = new Random(); Thread.sleep(random.nextInt(5000)); } }
SampleProducer.java
public class SampleProducer extends Thread { private int counter = 0; private SampleQueue queue; private String job; public SampleProducer(String job, SampleQueue queue) { this.queue = queue; this.job = job; } public void run() { try { while (true) { this.queue.order(job + " No." + this.counter); this.counter++; } } catch (InterruptedException e) { e.printStackTrace(); } } }
SampleProducer.java
public class SampleConsumer extends Thread { private SampleQueue queue; public SampleConsumer(SampleQueue queue) { this.queue = queue; } public void run() { try { while (true) { this.queue.work(); } } catch (InterruptedException e) { e.printStackTrace(); } } }
SampleProducerConsumerMain.java
public class SampleProducerConsumerMain { public static void main(String[] args) { SampleQueue queue = new SampleQueue(); new SampleProducer("System Designing", queue).start(); new SampleProducer("Programing", queue).start(); new SampleProducer("System Test", queue).start(); new SampleConsumer(queue).start(); new SampleConsumer(queue).start(); new SampleConsumer(queue).start(); } }
参考文献
java
http://www.hyuki.com/dp/dpinfo.html#ProducerConsumerhttp://pgcafe.moo.jp/JAVA/thread/main_7.htm
http://omiya6048.hatenablog.com/entry/2013/05/29/145253
BlockingQueue
http://blog.k11i.biz/2013/03/java-blockingqueue.html
.NET
http://blog.recyclebin.jp/archives/1714http://www.atmarkit.co.jp/ait/articles/0506/15/news114_2.html
http://www.makcraft.com/blog/meditation/2013/03/24/producer-consumer-pattern/