2
Javaの並行性に関する私の記憶をリフレッシュしていて、普及しているプロデューサのコンシューマの問題で遊んでいました。私は、単一のプロデューサーと単一のコンシューマーが存在する場合、正しく動作する以下のコードを実装しました。ただし、複数のプロデューサ/コンシューマが存在する場合、正しく機能しません。それ以外の場合は、いくつかのスレッドが目を覚ますと、条件がまだ満たされていない時に継続することができJavaの複数のプロデューサとコンシューマの問題(BlockingQueueなし)
while(condition not met)
wait();
:
public class ProducerConsumer {
static Monitor monitor;
public ProducerConsumer(int maxSize)
{
monitor = new Monitor(maxSize);
new Producer().start();
new Producer().start();
new Consumer().start();
new Consumer().start();
}
class Producer extends Thread{
@Override
public void run() {
while(true)
{
try {
monitor.insert();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer extends Thread{
@Override
public void run() {
while(true)
{
try {
monitor.remove();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Monitor {
int n;
int maxSize;
public Monitor(int maxSize)
{
n=0;
this.maxSize = maxSize;
}
synchronized void insert() throws InterruptedException
{
if(n==maxSize)
wait();
System.out.println("Producer: "+n++);
if(n==1)
notifyAll();
}
synchronized void remove() throws InterruptedException
{
if(n==0)
wait();
System.out.println("Consumer: "+n--);
if(n==maxSize-1)
notifyAll();
}
}
public static void main(String[] args) {
ProducerConsumer pc = new ProducerConsumer(100);
}
}
I second(パッド+1) – ant
ありがとうございました。しかし、スレッドが既に存在する場合、synchronizedメソッドはスレッドにそれを入力させることはできないと考えました。このコンセプトについて私が誤解したことは、この動作につながったのですか? – 3ashmawy
@ 3ashmawy:はい、スレッドが 'wait()'を呼び出すとロックを解除します。後続の 'notifyAll()'の起動後にスレッドが待ち行列に入り、ロックを再度取得して 'wait()'の後に続行します。明らかに、そのキュー内の最初のスレッドは状態を変更し、最後のスレッドは条件が再び満たされないことを検出します。 – axtavt