2009-09-01 13 views
29

プログラムの実行中に、いくつかのスレッドが開始されます。スレッドの量は、ユーザー定義の設定によって異なりますが、すべて同じメソッドを異なる変数で実行しています。複数のスレッドでJavaで完了するまで待ちます

状況によっては、実行中にクリーンアップが必要な場合があります。これはスレッドのすべてを停止していますが、すぐに停止しないようにするため、チェックする変数を設定します。問題は、スレッドが停止するまでに1/2秒までかかる可能性があるということです。ただし、クリーンアップを続行する前にすべてのスレッドが停止していることを確認する必要があります。クリーンアップは別のスレッドから実行されるので、技術的には、他のスレッドが終了するまでこのスレッドが必要です。

私はこれを行ういくつかの方法を考えましたが、それらはすべて過度に複雑であるようです。私はスレッドのグループが完了するのを待つことができるいくつかの方法があることを願っていました。このようなことは何ですか?

ありがとうございました。

for (Thread thread : threads) { 
    thread.join(); 
} 

(あなたがInterruptedExceptionで何かをする必要があります、あなたはうまく物事がうまくいかない場合には、タイムアウトを提供することもできますが、それは基本だ:

+0

[スレッドのセットが完了するのを待つ方法](http://stackoverflow.com/questions/) 1252190/how-to-for-threads-to-completion-for-threads-to-completion) –

答えて

49

ちょうど一つずつに参加しますアイデア...)

+0

これはうまくいくようですが、私のコードをリファクタリングして、クリーンアップメソッドでスレッド参照を取得する必要がありましたが、は働いている。それは今実行されている、ちょうど数分かかります。 –

+0

テストを完了しました。完璧に働いた。 –

+8

@Jon Skeet、私は疑いがある。 'thread.join();'という行はスレッド 'thread'が実行されるまで現在のプロセスを待ちます。ここで何が起きるかは、メインプロセスが2行目になり、 'thread'が作業を終了するのを待って、ループの次の' thread'に行くので、実際にメインスレッドは1番目の子スレッドが実行されるまで待機し、それは 'thread.join()'を次のスレッドのために実行します、そうですか? – Patriks

8

ユーティリティメソッド(またはメソッドを定義します)自分:

public static waitFor(Collection<? extends Thread) c) throws InterruptedException { 
    for(Thread t : c) t.join(); 
} 

それとも、配列

を有することができます
public static waitFor(Thread[] ts) throws InterruptedException { 
    waitFor(Arrays.asList(ts)); 
} 

別の方法としては、複数のスレッド間の任意のランデブーポイントを実装するためにjava.util.concurrentライブラリにCyclicBarrierを使用して見て可能性があります。

14

Java 1.5以降を使用している場合は、CyclicBarrierを試すことができます。クリーンアップ操作をそのコンストラクターパラメーターとして渡すことができ、クリーンアップが必要なときにすべてのスレッドに対してbarrier.await()を呼び出すだけです。

+0

ありがとう、これは私がこれを見たときに私が欲しいものをやったが、すでにジョンの答えを書いていたようだ。 –

+2

これを1回だけ実行する場合は、CountdownLatchを使用することもできます。 –

5

Executorクラスをjava.util.concurrentで見ましたか?スレッドはExecutorServiceで実行できます。これは、スレッドをキャンセルするか、完了するのを待つために使用できる単一のオブジェクトを提供します。

1

スレッドの作成(ExecutorServiceへの送信)を制御する場合は、ExecutorCompletionService ExecutorCompletionService? Why do need one if we have invokeAll?を参照してください。

スレッド作成を制御しない場合は、ruby ThreadWaitクラスに触発されているスレッドを「完了するたびに1つずつ結合する」ことができます(どのスレッドが最初に終了するかなどがわかります) 。 基本的には、他のスレッドが終了したときに警告する「監視スレッド」を新しくすることによって、多くの終了スレッドのうち「次の」スレッドがいつわかるのですか?

あなたはこのような何か、それを使用したい:

JoinThreads join = new JoinThreads(threads); 
for(int i = 0; i < threads.size(); i++) { 
    Thread justJoined = join.joinNextThread(); 
    System.out.println("Done with a thread, just joined=" + justJoined); 
} 

ソース:

public static class JoinThreads { 
    java.util.concurrent.LinkedBlockingQueue<Thread> doneThreads = 
     new LinkedBlockingQueue<Thread>(); 

    public JoinThreads(List<Thread> threads) { 
    for(Thread t : threads) { 
     final Thread joinThis = t; 
     new Thread(new Runnable() { 
     @Override 
     public void run() { 
      try { 
      joinThis.join(); 
      doneThreads.add(joinThis); 
      } 
      catch (InterruptedException e) { 
      // "should" never get here, since we control this thread and don't call interrupt on it 
      } 
     } 
     }).start(); 
    } 

    } 

    Thread joinNextThread() throws InterruptedException { 
    return doneThreads.take(); 
    } 
} 

本の素敵な部分は変更せずに、それは一般的なJavaスレッドで動作することで、任意のスレッド結合することができます。注意点は、追加のスレッドをいくつか作成する必要があることです。また、この特定の実装では、joinNextThread()を完全な回数呼び出さず、「close」メソッドなどを持たない場合には、「スレッドを後にしておく」こともできます。より洗練されたバージョンを作成したい場合は、ここにコメントしてください。スレッドオブジェクトなどの代わりに、この同じタイプのパターンを「先物」と共に使用することもできます。

関連する問題