2012-04-12 9 views
2

Javaのnotify()で少し混乱しています。次の例は、教科書の例です。Javaスレッドnotify()とnotifyAll()

public synchronized consume() { 
    while(queue.isEmpty()) { 
     try{ wait(); } catch (InterruptedException e) {} 
    } 
    // Assume that getElement() notifies to producers. 
    element = queue.getElement(); 
    ... 
} 

public synchronized produce() { 
    while(queue.isFull()) { 
     try{ wait(); } catch (InterruptedException e) {} 
    } 
    element = new Element(); 
    ... 
    queue.addElement(element); 
    notifyAll(); 
} 

私は上記の例ではproduce()という方法をよく理解しています。しかし、最初の方法(consume())の最後にnotifyAll()を使用しない理由を教えてもらえますか?要するに、これが好きではない理由:

public synchronized consume() { 
    while(queue.isEmpty()) { 
     try{ wait(); } catch (InterruptedException e) {} 
    } 
    // Assume that getElement() notifies to producers. 
    element = queue.getElement(); 
    ... 
    notifyAll(); 
} 

ありがとう!

よろしくお願いいたします。

答えて

6

は、私は同意するものとします。あなたのコード例では、キューから要素を削除しているので、誰かがisEmpty()ループで待機しているプロデューサに通知する必要があります。あなたのコードでは、しかし、言う:

// Assume that getElement() notifies to producers. 
element = queue.getElement(); 

だからコメントは何とかgetElement()notify()またはnotifyAll()を呼び出すことを意味します。略して

なぜこのようにしないで、はい

をあなたはコメントを削除する必要があるが、あなたのコードは動作します。 :-)

通常、これらのプロデューサ/コンシューマパターンには、キューが空のときと空のときの2つのロックがあります。その後、キューがいっぱいになっていなくてもでない場合、消費者はプロデューサに信号を送ることができません。は他のコンシューマーを目覚めさせます。この場合も、単一のコンシューマまたは単一のプロデューサを起動する必要があるだけなので、単一のnotify()を使用できます。 notifyAll()は、​​のオブジェクトが1つしか存在しないため、ここで使用されます。

はまた、後世のために、それはあなたがwhile()ループがないifステートメントをされて気づくことが非常に重要です。 notify()と2つのロックを使用している場合でも、保護する必要がある複数のプロデューサ/コンシューマモデルの競合状態があります。また、偽の起床も問題です。ここでその上より:

http://256stuff.com/gray/docs/misc/producer_consumer_race_conditions/

+0

ありがとう、グレー。 :-) –

1

この場合、通知は、消費するものがあることを消費者に知らせるために、生産時に使用され、そのうちの1つが目を覚まして消費することができます。消費者は単に何かを消費している

届出事業者は、getElement()内に発生すると想定されています。あなたは@Slashで

// Assume that getElement() notifies to producers. 
+0

@dlev正しい、編集を参照してください。 – EJP

+0

ありがとう、仲間。 :-) –

関連する問題