2013-12-11 16 views
5

大きなファイルがテラバイトまであり、私の仕事は1行ずつ処理することです。達成するためには、各行に5秒かかるはずです。私はこのExecutorServiceのキューがいっぱいになるとどうなりますか

ExecutorService executor = Executors.newFixedThreadPool(5);  

while ((line = br.readLine()) != null) { 
    Runnable worker = new WorkerThread(line); 
    executor.execute(worker); 
} 

のような固定スレッドプールへのプロセスをディスパッチパフォーマンスを向上させるために私の質問は、私は非常に多くのタスクを置くことによってエグゼキュータのキューを圧倒した場合に何が起こるかです。それはStackOverflowを投げますか?

+1

2年前私はインタビューでこの質問をしました:) – Vipin

+0

@Vipin:あなたは仕事を持っていますか? –

+2

私はこれに答えることができませんでした。いくつかの同様の質問の後、私は可能な限りJDKのソースコードを調べ始めました。デザインをよりよく理解するのに役立ちます。 – Vipin

答えて

4

あなたが入力するよりも速く処理しないと、OOMエラー(gcオーバーヘッド)が発生します。スタックがあまり変わらないので、StackOverflowを得ることはできません。

@StinePikeは良い質問をします。 RejectedExecutionExceptionは、キューからアイテムを処理するスレッドがなくなり、キューがいっぱいになった場合に発生します。この場合、デフォルトの実装Executors.newFixedThreadPool(5);は、無制限のLinkedBlockingQueueを使用します。あなたの唯一の制限は記憶です。

+2

RejectedExecutionExceptionがスローされますか? – stinepike

+2

@StinePikeキューが固定サイズの場合のみ、IIRCはデフォルトで無制限キューです。 –

+0

nice ..説明ありがとう+1 – stinepike

3

あなたはExecutors.newFiexedThreadPoolの実装を確認したよう、

public static ExecutorService newFixedThreadPool(int nThreads) { 
    return new ThreadPoolExecutor(nThreads, nThreads, 
            0L, TimeUnit.MILLISECONDS, 
            new LinkedBlockingQueue<Runnable>()); 
} 

タスクがLinkedBlockingQueueに投入し実行するスレッドを待つことになります。待機中のタスクが多すぎると、StackOverflowの代わりにOutOfMemoryがスローされる可能性があります。

2

newFixedThreadPoolは無制限ブロックキューを使用するため、OutOfMemoryErrorが発生します。バウンドキューを持つThreadPoolExecutorをインスタンス化することで、それを回避できます。

+0

バウンドとアンバウンドキューの違いは何ですか? –

+1

キューの容量についてです。容量[LinkedBlockingQueue(int capacity)]に制限がある場合(http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/LinkedBlockingQueue.html#LinkedBlockingQueue%28int%29) [LinkedBlockingQueue()](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/LinkedBlockingQueue.html#LinkedBlockingQueue%28%29)は無制限ですが、キューはバインドされています。 – Vasanth

4

これは少し話題になるかもしれませんが、この問題の1つのオプションは、固定長ブロックブロッキングを使用し、ThreadPoolExecutor.CallerRunPolicy()を使用することです。そうすれば、消費者が十分に速くない場合(つまりキューが満杯になった場合)、呼び出し元スレッド(プロデューサ)がタスク自体を実行するために利用されます。その場合には、

executorService = new ThreadPoolExecutor(DEFAULT_THREAD_COUNT, 
     DEFAULT_THREAD_COUNT, 2, TimeUnit.MINUTES, 
     new ArrayBlockingQueue<Runnable>(DEFAULT_QUEUE_LENGTH), 
     new ThreadPoolExecutor.CallerRunsPolicy()); 

From the API: を「executorがシャットダウンしていない限り、executeメソッドの呼び出し元のスレッドに直接拒否されたタスクを実行します拒否されたタスクのハンドラを:私たちは、次のようなエグゼキュータを初期化することができますタスクは破棄されます。

関連する問題