シーンの説明:
次のようにプロデューサ/コンシューマモデルでは、このシーンでは、学習プロセスとスレッドむしろ古典的な質問です:
、倉庫からのいくつかの生産者(プロデューサー)、いくつかの消費者(消費者)、製品(Procuct)と保存(プッシュ)倉庫を生成することができプロデューサーは、消費者が削除することができます(ポップ)倉庫(リポジトリ)がありますされており、消費者製品。
私が使用したいと考えて同期ロック機構と、(待機)/のnotifyAll()又は()通知メソッドの実装は、次のコードを。しかし、実際のテストは、notifyメソッドを使用している場合、スレッドは、スレッドは、ごく最近になって、使用時間をかけて、それが唯一の2つのスレッドが実際に実行されているになります通知ことがわかりました。使用のnotifyAll()メソッドは、倉庫実際の製品の最大数は、生産者の最大数だけ作成され、まだここで考え出した事前定義された独自の最大数に達することができません。目測は私のスレッドのメソッド呼び出しや通話の位置は解決に努め、方法に問題を起こしています。
実装コード:
import java.util.ArrayList;
/**
* 多生产者多消费者单仓库的生产者消费者模式
* @author breezefaith
*
*/
class Product{
private int productId;
public Product(int productId) {
super();
this.productId = productId;
}
@Override
public String toString() {
return "Product["+productId+"]";
}
}
class Repository{
private int maxSize;
private ArrayList<Product> list;
public Repository(int maxSize) {
super();
this.maxSize = maxSize;
list=new ArrayList<>(maxSize);
}
public void setMaxSize(int maxSize) {
if(maxSize<=list.size()) {
System.err.println("New size is smaller than the original.");
return;
}
ArrayList<Product> newList=new ArrayList<>(maxSize);
newList.addAll(list);
list=newList;
}
public int getMaxSize() {
return maxSize;
}
public int getCurrentSize() {
return list.size();
}
public void push(Product product) {
list.add(product);
}
public Product pop() {
return list.remove(0);
}
}
class Producer extends Thread{
private Repository repository;
private static int productId;
public Producer(Repository repository) {
super();
this.repository = repository;
}
public Product produce() {
Product product=new Product(productId++);
System.out.println("生产者 "+Thread.currentThread().getName()+" 生产了产品 "+product+",剩余:"+(repository.getCurrentSize()+1));
return product;
}
@Override
public void run() {
synchronized (repository) {
try {
while(true) {
Thread.sleep(1000);
if(repository.getCurrentSize()<repository.getMaxSize()) {
repository.push(produce());
}else {
System.err.println("Producer "+Thread.currentThread().getName()+" want to produce a product, but repository is full.");
}
repository.notifyAll();
repository.wait();
}
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer extends Thread{
private Repository repository;
public Consumer(Repository repository) {
super();
this.repository = repository;
}
public Product consume() {
Product product=repository.pop();
System.out.println("消费者 "+Thread.currentThread().getName()+" 消费了产品 "+product+",剩余:"+repository.getCurrentSize());
return product;
}
@Override
public void run() {
synchronized (repository) {
try {
while(true) {
Thread.sleep(1000);
if(repository.getCurrentSize()>0) {
consume();
}else {
System.err.println("Consumer "+Thread.currentThread().getName()+" consume a product, but repository is empty.");
}
repository.notifyAll();
repository.wait();
}
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Run {
public static void main(String[] args) {
Repository repository=new Repository(3);
Producer p1=new Producer(repository),
p2=new Producer(repository),
p3=new Producer(repository);
p1.setName("p1");
p2.setName("p2");
p3.setName("p3");
Consumer c1=new Consumer(repository),
c2=new Consumer(repository);
c1.setName("c1");
c2.setName("c2");
p1.start();
p2.start();
p3.start();
c1.start();
c2.start();
}
}
テスト結果:
1:生産者は残り、[0]商品産物を生成P1
0:残り、[0]消費者C1の消費者製品の製品を
消費者製品Aは、消費C2、しかし、リポジトリが空である。
[1]プロデューサが生成財製品をP3残り:1つの
2:残りプロデューサP2生成財製品[2]、
残りの生産P3生成品物[3]:3
消費者C2の消費者製品の製品を[1]、残り:2つの
消費者は、C1を消費します製品の製品[2]、残り:1つの
生産P1生成品物[4]、残り:2
消費者C1の消費者製品の製品[3]、残り:1つの
消費者C2の消費者製品の製品[4]、残り: 0
1:プロデューサは、生成品物[5]、残りP3
プロデューサーP2生成財製品を[6]、残り:2
生産P3生成品物[7]、残り:3
消費者製品C2の消費者製品を[5]残り:2
消費者C1の消費者製品の製品[6]、残り:1つの
[8]、残りの生産P1生成品製品:2