WaitとNotifyで「生産者-消費者」モデルを実現
前に書く
実際の開発では、あるモジュールがデータを生成し、共有バッファを介してフローし、最後に別のモジュールが処理するシーンがよく見られます.データを生成するモジュールを、イメージ的に生産者と呼ぶ.データを処理するモジュールは、消費者と呼ばれ、中間の倉庫は任意のバッファタイプの記憶媒体に抽象化することができる.
では、このモデルにはどんなメリットがありますか?第一に、生産者と消費者を分離し、結合度を低下させることができるデカップリングである.第二に、生産者は製造したデータをバッファに捨てると、次のデータを生産することができ、基本的に消費者の処理速度に依存する必要はありません.3つ目は、生産者と消費者の速度の違いを調整することができ、両者の速度を一致させる必要はありません.
生産者-消費者モデル
出力結果
ライセンス契約本文は創作共有CC BY-NC-SA 3.0プロトコル を遵守する.
実際の開発では、あるモジュールがデータを生成し、共有バッファを介してフローし、最後に別のモジュールが処理するシーンがよく見られます.データを生成するモジュールを、イメージ的に生産者と呼ぶ.データを処理するモジュールは、消費者と呼ばれ、中間の倉庫は任意のバッファタイプの記憶媒体に抽象化することができる.
では、このモデルにはどんなメリットがありますか?第一に、生産者と消費者を分離し、結合度を低下させることができるデカップリングである.第二に、生産者は製造したデータをバッファに捨てると、次のデータを生産することができ、基本的に消費者の処理速度に依存する必要はありません.3つ目は、生産者と消費者の速度の違いを調整することができ、両者の速度を一致させる必要はありません.
生産者-消費者モデル
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
public class ProducerConsumer {
public static void main(String[] args) throws InterruptedException {
final int maxSize = 3;
final LinkedList<String> queue = new LinkedList<String>();
final Thread producer = new Thread("producer-thread") {
@Override
public void run() {
while(true) {
synchronized (queue) {
while (queue.size() == maxSize) {
try {
System.out.println(Thread.currentThread().getName() + " , consumer ");
queue.wait();
System.out.println(Thread.currentThread().getName() + " , ");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
int index = queue.size();
queue.add("task-" + index);
System.out.println(Thread.currentThread().getName() + " task-" + index);
queue.notifyAll();
}
}
}
};
Thread consumer = new Thread("consumer-thread") {
@Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.isEmpty()) {
System.out.println(Thread.currentThread().getName() + " , producer ");
try {
queue.wait();
System.out.println(Thread.currentThread().getName() + " , ");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " " + queue.poll());
queue.notifyAll();
}
}
}
};
producer.start();
TimeUnit.MILLISECONDS.sleep(1); // producer
consumer.start();
}
}
出力結果
producer-thread task-0
producer-thread task-1
producer-thread task-2
producer-thread , consumer
consumer-thread task-0
consumer-thread task-1
consumer-thread task-2
consumer-thread , producer
producer-thread ,
producer-thread task-0
producer-thread task-1
producer-thread task-2
producer-thread , consumer
consumer-thread ,
consumer-thread task-0
consumer-thread task-1
consumer-thread task-2
consumer-thread , producer
producer-thread ,
producer-thread task-0
producer-thread task-1
producer-thread task-2
producer-thread , consumer
consumer-thread ,
consumer-thread task-0
consumer-thread task-1
consumer-thread task-2
consumer-thread , producer
producer-thread ,
producer-thread task-0
producer-thread task-1
Process finished with exit code 130 (interrupted by signal 2: SIGINT)
ライセンス契約