2016-07-28 1 views
1

スレッドには複数の状態があります。実行中の実行可能な実行中の待機中であり、終了しました。 notifyAll()メソッドは、オブジェクトのロック上に「待機中」のすべてのスレッドを「実行可能」状態に戻し、次の実行オブジェクトとして選択することが想定されています。 次の例では、 'calc'オブジェクトのロックが解除されるまで待機(wait()メソッド)する3つのReaderスレッドをインスタンス化して開始します。 calcオブジェクトスレッドはインスタンス化され、この後すぐにいくつかの数値を加算し、その後にnotifyAll()を追加します。スレッドnotifyAll()

私の質問は、calcスレッドが毎回すべてのリーダースレッドに通知するのはなぜですか?私はこれを私のコンピュータ上で実行すると、ヒットしてミスします。複数のスレッドを実行する際、スレッドの実行順序をが保証されない

public class Reader extends Thread{ 
    Calculator c; 

    public Reader(Calculator calc){ 
     c=calc; 
    } 

    public void run(){ 
     synchronized(c){ 
      try{ 
       System.out.println("Waiting for calculation..."); 
       c.wait(); 
      }catch(InterruptedException e){} 
      System.out.println("Total is: "+c.total); 
     } 
    } 
    public static void main(String[] args){ 
     Calculator calc = new Calculator(); 
     new Reader(calc).start(); 
     new Reader(calc).start(); 
     new Reader(calc).start(); 
     new Thread(calc).start(); 
    } 
} 
class Calculator implements Runnable{ 
    int total; 

    public void run(){ 
     synchronized(this){ 
      for(int i =0; i<100; i++){ 
       total+=i; 
      } 
      notifyAll(); 
     } 
    } 
} 
+0

'notifyAll()'はすぐにスレッドをRUNNABLEにしません。効果的に状態をWAITINGからBLOCKEDに変更します。スレッドAがオブジェクト 'o'のロックを獲得するまでは、スレッドAの' o.wait() 'コールは返ることができませんが、スレッドBがスレッド' o.notifyAll() 'を呼び出す時点でそれを行うことはできませんその呼び出しを行うには、Bがロックを保持している必要があります。 –

答えて

1

Calculatorスレッドがループを完了してnotifyAll()のスレッドが実行可能な状態になる前に呼び出している可能性があります。したがって、すべてReaderは待機し続け、決してtotalを印刷しません。

このような状況を回避するには、別のフラグisCalculatedCalculatorに使用し、計算が完了したらこのフラグを設定します。 Readerスレッドはまた、このフラグをチェックし、isCalculatedfalseの場合にのみ待機します。あなたが待機を呼び出す前に、いくつかのフラグをチェックすることができ@Sudhirで述べたように

class Reader extends Thread { 
    Calculator c; 

    public Reader(Calculator calc) { 
    c = calc; 
    } 

    public void run() { 
    synchronized (c) { 
     try { 
     System.out.println("Waiting for calculation..."); 

     if (!c.isCalculated) { // wait only if calculation is not done 
      c.wait(); 
     } 
     } catch (InterruptedException e) { 
     } 
     System.out.println("Total is: " + c.total); 
    } 
    } 
} 

class Calculator implements Runnable { 
    int total; 
    boolean isCalculated; 

    public void run() { 
    synchronized (this) { 
     for (int i = 0; i < 100; i++) { 
     total += i; 
     } 

     isCalculated = true; // set flag to mark that computation is complete 
     notifyAll(); 
    } 
    } 
} 
+0

さらに、私はこの問題の解決策を尋ねるつもりでした。ありがとう。 – JensD

+0

あなたは大歓迎です:) –

0

、 チェックはこのチュートリアル:待ち時間が呼び出される前に、あなたのケースのnotifyAll(にhttp://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html

が)と呼ばれてもよい。..ので、スレッドがよいです通知が呼び出されるのを待つことを続ける

+0

並行性は私の本(sierra k bates b java 7)の次の章です。私のOCPの準備には本当に良い本です。おそらく、私はすぐにすべてが明らかになるこの質問をして銃を飛ばしました。しかし、サンプルコードは警告音を鳴らしました。 – JensD

関連する問題