2017-08-11 18 views
0

私はwaitとnotifyAllの仕組みを理解し、ロードブロッキングを達成しました。waitとnotifyAllを使用するとJavaプログラムがフリーズします

このプログラムは、長いテキスト文書をダウンロードし、複数のスレッドを開始して文字数をカウントし、合計を出力します。

スレッド実行を制御してアルファベット順に完了させるために、waitとnotifyAllを使用しています。ここにコードがあります。私はその問題の説明に従います。

public class Test { 

    public static void main(String[] args) { 
    //code that reads in the data 

LongTask a = new LongTask(buffer, 'a', "Thread_a", 0); 
    a.start(); 

LongTask b = new LongTask(buffer, 'b', "Thread_b", 1); 
    b.start(); 

//Repeat code for all other characters 

a.join(); 

System.out.println("Alphabet count is: " + SharedResults.getResults()); 

LongTaskクラスは、コンストラクタと実行()

public class LongTask extends Thread { 
//Instance variables created here 

//LongTask constructor 
public LongTask (StringBuffer buffer, char target, String name, int turn) 
{ 
    super(name); 
    this.sharedData = sharedData; 
    inputData = buffer; 
    this.target = target; 
    this.turn = turn; 
} 


//Run method iterates through input data and counts matching characters, 
//then calls addToResults 
public synchronized void run() 
{ 
    //Thread t = Thread.currentThread(); 
    String name = this.getName(); 
    int runTurn = this.turn; 
    System.out.println(name + " running - Turn " + runTurn); 
    Integer count = 0; 
    for (int i = 0; i < inputData.length(); i++) { 
     if (inputData.charAt(i) == target) { 
     count ++; 
     } 
    } 
    ResultsEntry newResult = new ResultsEntry(count, target); 
    SharedResults.addToResults(newResult, turn); 
    } 
} 

SharedResultsクラスは、配列に結果が追加されますが含まれています。 addToResultsメソッドはこのアクションを実行し、同期を制御します。

public class SharedResults extends Thread{ 
//Code that creates array 
//Code for SharedResults constructor 

public synchronized static void addToResults(ResultsEntry newResult, int turn) 
{ 
    Integer resultsCount = newResult.getCount(); 
    char resultsTarget = newResult.getTarget(); 
    Thread t = Thread.currentThread(); 

    /* 
    * Turn number is compared to the size of the results array to control the 
    * order of execution. 
    */ 
    while (turn != results.size()){ 
     try { 
      System.out.println("Wait printout"); 
      t.wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
    } 
    System.out.println(t.getName() + " is adding " + newResult); 
    SharedResults input = new SharedResults(resultsCount, resultsTarget); 
    System.out.println("Cumulative Results are " + results);  
    t.notifyAll();  
    } 

この手順をデバッグで見ると、次のようなことが起こります。 - 入力が実行され、すべてのLongTaskスレッドが(Thread_aがaddToResultsを実行するための最初のスレッドでなければなりません)

- いくつかのスレッド(ないThread_a)

を開始するには、addToResultsの中の評価をヒットし、

を続行しないでください - Thread_aは評価中にヒットし、完全に実行されます。

-Thread_eは、「プリント待ち」(スレッドが待機していることを通知するデバッグ機能)を実行し、プログラムがハングアップします。

私は正しく待ち時間を設定していないように見えます。 sysoutに追加するまで、プログラムは実際に正しく機能していました(または、そうであるように見えました)。ここで起こっていることは何ですか?

+0

ここでのロックの仕組みは混乱します。ロックを使用して共有データ構造(データ構造がロックを使用して自己へのアクセスを制限する)を保護する場合、スレッドによってロックが行われるのではなく、混乱が少なくなります。 –

+0

Re、 "スレッド実行を制御するためにwaitとnotifyAllを使用して、アルファベット順に完了します。"あなたが間違った方向にあなたの旅を始めているように聞こえます。あなたが特定の順序で物事をするようにスレッドを強制すると、スレッドのアイデアを覆すことになります。これは、同時に(つまり、特に順序なく)何かを行うことです。) –

+0

'public synchronized void run()'これは絶対に悪い考えです。 –

答えて

0

これは、問題はのnotifyAll()が待っているそのオブジェクトのすべてのスレッドに通知することをあるthis thread.

で覆われていた、自分の質問に答えるために。私は各スレッドでwait()を呼び出していたので、別のスレッドからのnotifyAll()は他のスレッドに通知していませんでした。

リンクされたポストで示唆されているように、私は静的な同期オブジェクトを作成し、そのオブジェクトに対してwaitおよびnotifyメソッドを呼び出しました。結果のコードは次のようになります。 private static final Object LOCK = new Object();

public static void addToResults(ResultsEntry newResult, int turn) 
{ 
    Integer resultsCount = newResult.getCount(); 
    char resultsTarget = newResult.getTarget(); 
    Thread thread = Thread.currentThread(); 

    /* 
    * Turn number is compared to the size of the results array to control the 
    * order of execution. 
    */ 
    synchronized (LOCK){ 
     while (turn != results.size()){ 
      try { 
       System.out.println(thread.getName() + " is waiting"); 
       LOCK.wait(); 
       } catch (InterruptedException e) {} 
     } 
      System.out.println(thread.getName() + " is adding " + newResult); 
      SharedResults input = new SharedResults(resultsCount, resultsTarget); 
      System.out.println("Cumulative Results are " + results);  
      LOCK.notifyAll(); 
     } 
     } 

コメントありがとうございました!

関連する問題