1

複数のスレッドからアクセスされるクラスがあり、各スレッドはこのクラスの 1 つのメソッドを要求します。各メソッドは、順番に Callable の数を実行します。このクラスは、ExecutorService の threadPool を使用して、invokeAll((Collection>) executableTasks) メソッドを通じてこれらの Callable を実行します。セットアップは次のようになります。

public MyClass {
private final ExecutorService threadPool = Runtime.getRuntime().availableProcessors();

public void method1() {
 List<SomeObject> results = new ArrayList<>();
 List<Callable<Void>> tasks = new ArrayList<Callable<Void>>();
 tasks.add(new Callable<Void>(){ ... results.add(someObject);} );
 threadPool.invokeAll(tasks);
}

public void method2() {
 List<SomeObject> results = new ArrayList<>();
 List<Callable<Void>> tasks = new ArrayList<Callable<Void>>();
 tasks.add(new Callable<Void>(){ ... results.add(someObject);} );
 threadPool.invokeAll(tasks);
}

}

これがクラス内のタスクを同時に実行するのか、それともinvokeAll()が1つのメソッド内のタスクが完了するまで実行をブロックするのか混乱しています(クラスレベルではなくメソッド内で同時に実行されることを意味します)? または、対応するタスクの結果を見つけるために CompletionService を使用する必要がありますか?

4

3 に答える 3

2

ExecutorService#invokeAllはすべてのタスクを同時に実行しますが、呼び出し自体はすべてのタスクが完了するまでブロックされます。

たとえば、完了するのに 6 秒、2 秒、10 秒かかる 3 つのタスクがあるとします。これらを同期的に実行すると、少なくとも 6 + 2 + 10 = 18 秒かかります。ただし、invokeAll を (十分に大きなスレッド プールで) 使用すると、最長時間 (10 秒) しかかからない可能性があります。

これは、メソッドmethod1()method2()が両方とも を使用しているため、メソッドをブロックしていることを意味しますinvokeAll()。を呼び出すとmethod1()、callable のリストに追加されたすべてのリクエストが完了するまでブロックされます。についても同様ですmethod2()。これらのメソッドが異なるスレッドから呼び出された場合、両方のメソッドのタスクが同時に実行されます。

メソッドを非同期にしたい場合は、メソッド内のタスクごとに個別に threadPool.submit(callable) を呼び出し、返された Future をリストに収集します。List を返すか、CompletionService を使用してこれを支援することができます。

PS - あなたの例のこの行は機能しません:

ExecutorService threadPool = Runtime.getRuntime().availableProcessors();

代わりにこれが欲しいと思います:

ExecutorService threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

お役に立てれば。

于 2013-05-17T04:04:35.390 に答える
0

私にとって、これはクラス内のタスクを同時に実行します。invokeAll()すべてのタスクが完了するまで待機しますが、それは現在のスレッド用です。このスレッドが待機している間、他のスレッドはそのタスクを同時に実行できます

于 2013-05-17T04:04:31.187 に答える
-1

Java 仕様に従って、invokeAllすべてのタスクを互いに独立して同時に実行します。を繰り返し呼び出してinvokeAllも同じことが行われます。つまり、invokeAllタスクの実行をブロックしないように呼び出します。

訪問: http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/AbstractExecutorService.html

于 2013-05-17T04:03:45.243 に答える