8

Javaのフレームワークを使用してExecutors、マルチスレッドアプリケーションのスレッドプールを作成していますが、パフォーマンスに関する質問があります。

リアルタイムモードまたは非リアルタイムモードで動作できるアプリケーションがあります。リアルタイムの場合、私は単に以下を使用しています:

THREAD_POOL = Executors.newCachedThreadPool();

ただし、リアルタイムでない場合は、スレッドプールのサイズを制御できるようにする必要があります。これを行うために、私は2つのオプションについて考えていますが、違いがよくわかりません。どちらがパフォーマンスが優れているのでしょうか。

オプション1は、次の簡単な方法を使用することです。

THREAD_POOL = Executors.newFixedThreadPool(threadPoolSize);

ThreadPoolExecutorオプション2は、次のように自分で作成することです。

RejectedExecutionHandler rejectHandler = new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
    try {
        executor.getQueue().put(r);
    } catch (Exception e) {}
}
};          
THREAD_POOL = new ThreadPoolExecutor(threadPoolSize, threadPoolSize, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(10000), rejectHandler);

より複雑なオプション2を使用する利点は何か、また、他のデータ構造を使用する必要があるかどうかを理解したいと思いLinkedBlockingQueueます。どんな助けでもいただければ幸いです。

4

1 に答える 1

14

ソースコードを見ると、次のことがわかります。

Executors.newFixedThreadPool(threadPoolSize);

同等です:

return new ThreadPoolExecutor(threadPoolSize, threadPoolSize, 0L, MILLISECONDS,
                              new LinkedBlockingQueue<Runnable>());

明示的ではないためRejectedExecutionHandler、デフォルトAbortPolicyが使用されます。RejectedExecutionException基本的に、キューがいっぱいになるとスローされます。ただし、キューには制限がないため、キューがいっぱいになることはありません。したがって、このエグゼキュータは、無限の1つのタスクを受け入れます。

あなたの宣言ははるかに複雑で、まったく異なります。

  • new LinkedBlockingQueue<Runnable>(10000)10000を超える待機中の場合、スレッドプールはタスクを破棄します。

  • あなたが何をしているのかわかりませんRejectedExecutionHandler。プールがそれ以上実行可能ファイルをキューに入れることができないことを検出すると、ハンドラーを呼び出します。このハンドラーでは、...Runnableそれをもう一度キューに入れてみてください(ケースの99%のように失敗しますブロック)。最後に、例外を飲み込みます。あなたが求めているのThreadPoolExecutor.DiscardPolicyはそうです。

    以下のコメントを見ると、タスクキューが大きすぎる場合に、クライアントをブロックまたは何らかの方法で抑制しようとしているように見えます。RejectedExecutionHandler内部をブロックするのは良い考えではないと思います。代わりに、CallerRunsPolicy拒否ポリシーを検討してください。完全に同じではありませんが、十分に近いです。

まとめ:保留中のタスクの数を制限したい場合は、アプローチはほぼ適切です。同時スレッドの数を制限したい場合は、最初のワンライナーで十分です。

1-2^31が無限大であると仮定

于 2013-01-11T20:53:37.710 に答える