3

Collection<Callable<T>> tasksを作成して呼び出して使用する、スレッドプールを多用するコードがいくつかありますExecutorService.invokeAll(tasks)

for (Future<Object> future : threadPool.invokeAll(tasks)) {
  Object object = future.get();
  // Calling thread effectively blocks on invokeAll().
}

私のアプリでは、のサイズはtasks大きく異なります。実際、ほとんどの場合、は単一のタスクExecutorService.invokeAll()で呼び出されます。私が使用しているの実装は、その実装は常にスレッドプールでタスクを実行するように見えます(呼び出しスレッドでは決してありません)。invokeAll()ThreadPoolExecutor.execute()

単一のタスクの場合、別のスレッドに送信するよりも、現在のスレッドでタスクを呼び出す方が効率的でしょうか?

4

2 に答える 2

3

単一のタスクの場合、別のスレッドに送信するよりも、現在のスレッドでタスクを呼び出す方が効率的ですか?

はい、それはより効率的でしょう。しかし、それは興味深い質問ではありません。興味深い質問は、それがどれほど非効率的であるか(タスクが何をしているかによって異なります)、およびアプリケーションでこれを十分に実行して全体的に重要になるかどうかです。

それを評価するのに十分な情報がありません。1つの些細なタスク(「マップから値をフェッチする」)を1秒間に数百万回実行している場合、スレッドプールを介したすべての間接参照が実際の違いを生む可能性があります。タスクが実際にかなりの量の作業を行う場合、タスクが1つしかない場合に備えて、特別なコードを追加する価値はほとんどありません。

于 2012-06-27T06:01:25.770 に答える
2

もちろん、コードを適切な場所で実行するだけで、コードを実行するための総コストがいくらか削減されます。コレクションの構築、キューイングとデキューイング、ワーカースレッドのウェイクアップ、CPUがタイムシェアリングする必要のある現在の合計に別のスレッドを追加する、あるスタックから別のスタックにデータを移動するなどではありません。

ただし、効率が高くても「正しく」なるわけではありません。現在のスレッドは通常、かなり時間に敏感なことを行っており、作業が完了するのを待たずに、主な関心事であるタスクに戻ることができるように、作業をプールに渡します。

「currentThread」がメインのGUIスレッドであり、たとえば30秒かかる印刷スプールジョブを詐称通用している場合、ExecutorServiceの実装では、「ああ、ここにはジョブが1つしかないので、実行するだけです。現在のスレッドでは」という行為は非常に間違っており、ユーザーは30秒のハングアップでそれがどれほど間違っているかを通知します。

于 2012-06-27T06:03:03.683 に答える