2013-01-11 10 views
7

JavaのExecutorsフレームワークを使用してマルチスレッドアプリケーション用のスレッドプールを作成しています。Executorsサービスを使用してJavaで固定サイズのスレッドプールを作成する最適な方法

私は、リアルタイムまたは非リアルタイムモードで動作するアプリケーションを持っています。場合には、それはリアルタイムだ、私は単純に次のように使用しています:

THREAD_POOL = Executors.newCachedThreadPool(); 

しかし、それは、リアルタイムいない場合には、私は私のスレッドプールのサイズを制御する機能が欲しいです。 これを行うには、私は2つのオプションについて考えていますが、私は実際にその違いを理解しておらず、どちらが良いでしょうか。

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

THREAD_POOL = Executors.newFixedThreadPool(threadPoolSize); 

オプション2は、このような自分のThreadPoolExecutorを作成することです:

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よりも別のデータ構造を使用する必要がある場合は?どんな助けもありがとう。

答えて

13

ソースコードを見ると、あなたはそれを実現します:それはRejectedExecutionHandler明示、デフォルトAbortPolicyが使用されていませんので

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

Executors.newFixedThreadPool(threadPoolSize); 

はと同等です。キューがいっぱいになると基本的にRejectedExecutionExceptionがスローされます。しかし、待ち行列には無制限なので、決して満杯にならない。したがって、このエグゼキュータはinifnite 個のタスクを受け入れます。

あなたの宣言は、はるかに複雑で、かなり異なっている:

  • new LinkedBlockingQueue<Runnable>(10000)が10000を超えるが待っている場合は、スレッド・プールには、タスクを破棄するようになります。

  • 私はあなたのRejectedExecutionHandlerがやっていることを理解していません。プールが発見した場合、キューにランナブルをもうけることができません。キューにはハンドラが呼び出されます。このハンドラでは、... Runnableをキューに再度入れてみてください(は、ケースの99%のように失敗します)。最後に例外を飲み込む。 ThreadPoolExecutor.DiscardPolicyのように思えます。

    タスクのキューが大きすぎる場合は、ブロックしようとしているか、何らかの原因でクライアントを絞り込んでいるようです。私はRejectedExecutionHandlerの内部をブロックすることは良い考えだとは思わない。代わりに、CallerRunsPolicy拒否ポリシーを検討してください。全く同じではないが、十分に近い。

解決方法:保留中のタスクの数を制限したい場合は、アプローチはほぼ良好です。並行スレッドの数を制限したい場合は、最初の1つのライナーで十分です。

1 - 想定2^31は無限

+0

ある 'RejectedExecutionHandler'は実際、executor.getQueue()'へのコールをブロックして置く(R);キューが解放されるまで 'ブロックしますので。最終的に私のハンドラは任意のタスクを中止することなく境界キューを保持することができます。私が間違っていない限り。他の詳細については+1。 –

+0

@CharlesMenguy:明確化のためにありがとう、私の悪い、私は私の質問を更新します。しかし、 'RejectedExecutionHandler'の内部をブロックすることで何を達成したいですか?私はそれが呼び出し側のスレッドをブロックするような、本当に予期せぬ副作用があるかもしれないと考えていますたぶんあなたは 'CallerRunsPolicy'を必要としますか? –

+0

実際にそれを見た後、 'CallerRunsPolicy'は本当に私がやりたいことを約束しています。私は試してみてください!たぶんあなたは答えにそれを追加することができ、私はあなたの答えを受け入れるでしょう。 –

関連する問題