Java サンプル - プロデューサー/コンシューマー問題
プロデューサーとコンシューマーの問題は、スレッドモデルにおける古典的な問題です。プロデューサーとコンシューマーは同じ時間帯に同じストレージ領域を共有します。下図のように、プロデューサーは領域にデータを格納し、コンシューマーはデータを取り出します。調整を行わないと、以下のような状況が発生する可能性があります。
ストレージ領域が満杯なのに、プロデューサーがそれを占有している場合、コンシューマーはプロデューサーが領域を空けるのを待って製品を取り出し、プロデューサーはコンシューマーが製品を消費するのを待って領域に製品を追加します。互いに待ち合うことで、デッドロックが発生します。

以下のサンプルは、スレッドを使用してプロデューサー/コンシューマー問題を解決する方法を示しています。
サンプル
/*
author by example.com
ProducerConsumerTest.java
*/
public class ProducerConsumerTest {
public static void main(String[] args) {
CubbyHole c = new CubbyHole();
Producer p1 = new Producer(c, 1);
Consumer c1 = new Consumer(c, 1);
p1.start();
c1.start();
}
}
class CubbyHole {
private int contents;
private boolean available = false;
public synchronized int get() {
while (available == false) {
try {
wait();
}
catch (InterruptedException e) {
}
}
available = false;
notifyAll();
return contents;
}
public synchronized void put(int value) {
while (available == true) {
try {
wait();
}
catch (InterruptedException e) {
}
}
contents = value;
available = true;
notifyAll();
}
}
class Consumer extends Thread {
private CubbyHole cubbyhole;
private int number;
public Consumer(CubbyHole c, int number) {
cubbyhole = c;
this.number = number;
}
public void run() {
int value = 0;
for (int i = 0; i < 10; i++) {
value = cubbyhole.get();
System.out.println("コンシューマー #" + this.number+ " got: " + value);
}
}
}
class Producer extends Thread {
private CubbyHole cubbyhole;
private int number;
public Producer(CubbyHole c, int number) {
cubbyhole = c;
this.number = number;
}
public void run() {
for (int i = 0; i < 10; i++) {
cubbyhole.put(i);
System.out.println("プロデューサー #" + this.number + " put: " + i);
try {
sleep((int)(Math.random() * 100));
} catch (InterruptedException e) { }
}
}
}
author by example.com
ProducerConsumerTest.java
*/
public class ProducerConsumerTest {
public static void main(String[] args) {
CubbyHole c = new CubbyHole();
Producer p1 = new Producer(c, 1);
Consumer c1 = new Consumer(c, 1);
p1.start();
c1.start();
}
}
class CubbyHole {
private int contents;
private boolean available = false;
public synchronized int get() {
while (available == false) {
try {
wait();
}
catch (InterruptedException e) {
}
}
available = false;
notifyAll();
return contents;
}
public synchronized void put(int value) {
while (available == true) {
try {
wait();
}
catch (InterruptedException e) {
}
}
contents = value;
available = true;
notifyAll();
}
}
class Consumer extends Thread {
private CubbyHole cubbyhole;
private int number;
public Consumer(CubbyHole c, int number) {
cubbyhole = c;
this.number = number;
}
public void run() {
int value = 0;
for (int i = 0; i < 10; i++) {
value = cubbyhole.get();
System.out.println("コンシューマー #" + this.number+ " got: " + value);
}
}
}
class Producer extends Thread {
private CubbyHole cubbyhole;
private int number;
public Producer(CubbyHole c, int number) {
cubbyhole = c;
this.number = number;
}
public void run() {
for (int i = 0; i < 10; i++) {
cubbyhole.put(i);
System.out.println("プロデューサー #" + this.number + " put: " + i);
try {
sleep((int)(Math.random() * 100));
} catch (InterruptedException e) { }
}
}
}
上記のコードを実行した出力結果は次のとおりです。
消费者 #1 got: 0 生产者 #1 put: 0 生产者 #1 put: 1 消费者 #1 got: 1 生产者 #1 put: 2 消费者 #1 got: 2 生产者 #1 put: 3 消费者 #1 got: 3 生产者 #1 put: 4 消费者 #1 got: 4 生产者 #1 put: 5 消费者 #1 got: 5 生产者 #1 put: 6 消费者 #1 got: 6 生产者 #1 put: 7 消费者 #1 got: 7 生产者 #1 put: 8 消费者 #1 got: 8 生产者 #1 put: 9 消费者 #1 got: 9その他の拡張
Java サンプル