2017-02-25 1 views
0

私は、複数のスレッドを持つプログラムを書いています。そのプログラムの中で 私はしばしばwaitとnotifyを使って、あるスレッドが他のスレッドが起動するまで待つようにします。Javaのスレッドを2つのスレッドから通知を受け取るようにするには?

私の想像上のプロジェクトでは、私は3つのスレッドがあると言うことができます:m、aとb。 mはメインです。 mスレッドはスレッドを開始し、bスレッドを開始します。 mスレッドはあるスレッドがそのジョブで完了するのを待つべきです(死ぬことはしません)。もし完了すれば、目覚めて一つのことをしなければならない。 bが完了すれば、目覚めて別のことをするべきです。このような

と何かを::

私がmでこのようなものを使用することができ、私はBを待ちたい場合

synchronized(this) 
{ 
    notify(); 
} 

同じことが行きます。

synchronized(this) 
{ 
    notify(); 
} 

しかし、私はそれらの両方を待ちたい場合、私はこのようなコード必要があります:

Bで
synchronized(b) 
{ 
    b.wait(); 
} 

:メートルで

synchronized(a, b) 
{ 
    a,b.wait(); 
} 

もちろんのを、これはjavaではサポートされていません。

もちろん、メインをスリープ状態(32)にしたり、そのようなものを入れて、フラグをaとbに入れたり、起きるとフラグをチェックしたり、どちらが終了したかを知ることができます。 しかし、私はwait-notifyアプローチを使って、aとbのフラグを常にチェックすることを避けたかったのです。

だから、解決策は何ですか? 何か方法がありますが、フラグが常にチェックされている以外、mからaまたはbが終了した(死んでいない)ことがわかりましたか?

+0

あなたの説明はちょっと混乱します。 'm'は' a'と 'b'が終わるのを待つか、' a'か 'b'が終わるたびに' m'に戻ってほしいですか? 'b'との継続作業や全く別の作業をしている作品は? – Esko

+0

はい、mはaまたはbのいずれかを待つ必要があります。 aとbは多段階の仕事をしています。 1つのステージで終了するたびに、それをmに通知したい。 1つのステージでbが終了すると、mにも通知する必要があります。 mがmに通知すると、mは "a notified me"と、bがmに通知すると、mは "b通知された"と書かれたようなことをする必要があります。 –

答えて

1

メインスレッドmを持つためには反応します。

最も簡単な例では、mは依存するスレッドをリストに保持し、2つのループで最初に他のスレッドを開始した後、別のループでそのスレッドが終了するまで待機します。java.util.concurrent.BlockingQueue

  • ほとんど同じ使用を使用して

    • メッセージは、スレッド間を通過する:このような何かを達成するために利用できる他のソリューションの多くがあります

      public class MainThread { 
          public void run() { 
           List<Thread> threads = Arrays.asList(
            new Thread(() -> react(this)), 
            new Thread(() -> react(this)), 
           ); 
           // start all threads first to avoid deadlock 
           threads.forEach(Thread::start); 
           // wait for all threads to finish in order 
           threads.forEach(Thread::join); 
           // here you can do whatever post steps you want 
          } 
          public void react(Thread t) { 
           System.out.print("MainThread called by " + t); 
          } 
      } 
      

      :だから、あなたは、このような何かを持っている必要があります大文字小文字の区別がある場合java.util.concurrent.CountdownLatch

    • @ john16384最終結果をキャッチ/最終値を返すことが重要でない場合は、java.util.concurrent.CompletableFuture

    など。

  • +0

    大丈夫、これは参考になりました。 –

    1

    共有オブジェクトに対して同期(待機、通知)を実行できます。多分私は?代わりにaまたは完全なbは、ちょうどaを持っているとbが正しいことを行うときmは物事を行うことの

    1

    私はCompletableFutureでこれをやってお勧めします:子スレッド(この場合ab)のいずれかが、いくつかのオプションがあります作業終了後

    CompletableFuture.runAsync(<thread A>) 
        .thenRun(<stuff that should be done after A completes>); 
    
    +0

    追加の文脈がなければ、「正しいこと」は、メインスレッドに何をしていても何の処理も続けることができるかもしれません。 – Esko

    +0

    ええ、ここでは、この種の問題に匹敵しないイディオムを使用するのではなく、問題を単純化するために書き直すことを提案しています。 – john16384

    +0

    これはおそらく問題を単純化しません。前述のように、より多くのコンテキストが必要です。提案されたイディオムは、並列実行のフォーク/結合モデル全体の「結合」部分を実際に処理するという概念を取り除きます。 – Esko

    0

    あなたの文脈では、CompletableFutureを使用して目的を果たします。

    関連する問題