4

次の(Java)コードを含むメソッドがあります。

doSomeThings();
doSomeOtherThings();

doSomeThings()いくつかのスレッドを作成します。各スレッドは限られた時間だけ実行されます。doSomeOtherThings()問題は、によって起動されたすべてのスレッドが終了するまで呼び出されたくないということですdoSomeThings()。(また、新しいスレッドなどを起動する可能性のあるメソッドを呼び出します。これらのスレッドがすべて終了するまでdoSomeThings()実行したくありません。)doSomeOtherThings()

これはdoSomeThings()、とりわけ、に設定さmyObjectれるためですがnulldoSomeOtherThings()電話をかけている間、私はその時にmyObject.myMethod()なりたくありません。myObjectnull

この種のことを(Javaで)行うための標準的な方法はありますか?

4

6 に答える 6

10

java.util.concurrentパッケージをご覧になることをお勧めします。特に、次のCountDownLatchように使用することを検討してください。

package de.grimm.game.ui;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {

public static void main(String[] args) 
throws Exception {

    final ExecutorService executor = Executors.newFixedThreadPool(5);
    final CountDownLatch latch = new CountDownLatch(3);

    for( int k = 0; k < 3; ++k ) {

        executor.submit(new Runnable() {
            public void run() {
                // ... lengthy computation...
                latch.countDown();
            }
        });
    }

    latch.await();

    // ... reached only after all threads spawned have
    // finished and acknowledged so by counting down the
    // latch.

    System.out.println("Done");
}
}

明らかに、この手法は、フォークされたスレッドの数を事前に知っている場合にのみ機能します。これは、その数でラッチを初期化する必要があるためです。

別の方法は、次のような条件変数を使用することです。

boolean done = false;

void functionRunInThreadA() {

    synchronized( commonLock ) {

        while( !done ) commonLock.wait();
    }

    // Here it is safe to set the variable to null
}

void functionRunInThreadB() {

    // Do something...

    synchronized( commonLock ) {
        done = true;
        commonLock.notifyAll();
    }
}

InteruptedException例外処理( )などを追加する必要があるかもしれません。

于 2010-04-05T19:52:37.490 に答える
6

メソッドを見てくださいThread.join()

正確な実装についてはわかりませんが、doSomeThings()は子スレッドを待ってから戻る必要があるようです。

doSomeThings()メソッド内で、Thread.join()メソッドを呼び出してスレッドを待機します。

スレッドを作成してそのスレッドのjoin()メソッドを呼び出すと、呼び出し元のスレッドはそのスレッドオブジェクトが終了するまで待機します。

例:

// Create an instance of my custom thread class
MyThread myThread = new MyThread();
// Tell the custom thread object to run
myThread.start();
// Wait for the custom thread object to finish
myThread.join();
于 2010-04-05T19:45:57.407 に答える
3

あなたが探しているのはexecutorserviceであり、先物を使用します:)

http://java.sun.com/docs/books/tutorial/essential/concurrency/exinter.htmlを参照してください

したがって、基本的に、エグゼキュータサービスに送信するすべてのランナブルの先物を収集します。すべての先物をループし、get()メソッドを呼び出します。これらは、対応するランナブルが完了すると返されます。

于 2010-04-05T19:54:42.903 に答える
1

CountdownLatchと同様の機能を実行するために使用できるもう1つの便利で堅牢な同期バリアは、 CyclicBarrierです。これは、使用されているパーティ(スレッド)の数を知る必要があるCountdownLatchと同様に機能しますが、毎回CountdownLatchの新しいインスタンスを作成するのではなく、バリアを再利用できます。

私は、ExecutorServiceを使用し、先物を収集し、完了するまでそれらすべてを呼び出すというmomaniaの提案が好きです。

于 2010-04-05T21:12:39.450 に答える
0

もう1つのオプションは、メインスレッドをスリープ状態にし、他のスレッドが終了したかどうかを頻繁にチェックすることです。ただし、DirkとMarcusAdamsの回答の方が好きです。完全を期すためにこれをここに捨てるだけです。

于 2010-04-05T19:55:10.637 に答える
0

ここで何をしようとしているのかによって異なります。あなたの主な関心事は、内部から呼び出される連続するメソッドによって生成されるさまざまなスレッドを動的に判別doSomeThings()し、それらが終了するまで待ってから呼び出すことができる doSomeOtherThings()かどうかです。または、コンパイル時に生成されるスレッドを知ることは可能ですか?後者の場合、いくつかの解決策がありますが、基本的には、Thread.join()作成された場所からこれらすべてのスレッドでメソッドを呼び出す必要があります。

それが実際に前者である場合は、ThreadGroupとそのenumerate() 方法を使用することをお勧めします。これにより、ThreadGroupに新しいスレッドを適切に追加した場合に、doSomeThings()によって生成されたすべてのスレッドの配列が得られます。次に、返された配列内のすべてのスレッド参照をループして、join() を呼び出す直前にメインスレッドを呼び出すことができますdoSomeOtherThings()

于 2010-04-08T23:37:31.690 に答える