4

私はExecutor特にフレームワークを使用しています。たとえば100のExecutors.newCachedThreadPool();
リストがあります。 最初の50は、それぞれが最後の50で使用される値(リストに格納されている)を作成 します。それらはリストにあり、同じ順序で実行されます。 しかし、これは起こっていません。 タスクはランダムな順序で実行されているように見え、順番に実行されるのではなく、インターリーブされます。 これはどのように機能するのでしょうか?この問題を回避する方法はありますか?Runnable

Runnableexecutor.execute()


ありがとう

4

3 に答える 3

10

ジョブを2つのバッチで送信するか、明示的な「happens-before」関係を作成する必要があります。ジョブの2つのバッチを作成し、使用することをお勧めしますinvokeAll(batch1); invokeAll(batch2); 。このinvokeAll()メソッドはすべてのタスクを実行し、完了するまでブロックします。Runnablesをsとしてラップする必要がある場合がありCallableます。これは、で行うことができますExecutors.callable(Runnable r)。(@Cameron Skinnerは、コード例を取得するために私を打ち負かしました。詳細については、その回答を参照してください...)

エグゼキュータの全体的なポイントは、実行の詳細を抽象化することであるため、明示的に指定されていない限り、順序付けは保証されません。厳密に順次実行する場合は、実行しているスレッド(最も単純)で実行するか、シングルスレッドのエグゼキューターalaExecutors.newSingleThreadExecutor()で実行するか、タスクを明示的に同期します。後者を実行する場合は、バリアまたはラッチを使用して、依存タスクをバリア/ラッチでブロックすることができます。また、タスクの最初のブロックに実装Callable、returnFutureを設定し、依存タスクを呼び出しmyFuture.get()て、結果が返されるまでブロックさせることもできます。

特定のアプリケーションについて詳しくお話しいただければ、より具体的にサポートできる可能性があります。

于 2010-12-17T12:39:48.380 に答える
7

それが正しい振る舞いです。Runnablesが実行される順序についての保証はありません。

エグゼキュータは並列で実行されますが、タスクはシリアルで実行する必要があるようです。最初の50個のジョブを送信し、それらが完了するのを待ってから、次の50個のジョブを送信するか、(実行の順序が重要な場合)すべてを単一のスレッドで実行することができます。

例えば、

for (Future<Whatever> f: service.invokeAll(first50tasks)) {
    addResultToList(f.get());
}
Future<Whatever> output = service.invokeAll(second50tasks);
于 2010-12-17T12:43:53.430 に答える
2

おそらくexecute、最初の50、shutdownそしてawaitTermination、そしてexecute他の50だけが可能でしたか?いくつかのサンプルコードについては、この回答を参照してください。

于 2010-12-17T12:40:13.187 に答える