ExecutorCompletionService 的幾點認識

ExecutorCompletionService  通常與 ThreadPoolExecutor一起使用
ThreadPoolExecutor構造時可以帶 BlockingQueue<Callable>初始化,稱爲workQueue;而ExecutorCompletionService 也可以帶BlockingQueue<Future>初始化,稱爲completionQueue

幾點認識

1.  ExecutorService的 workQueue是控制任務提交的,如果workQueue滿了,採用RejectedExecutionHandler的策略:有Abort, CallerRun 等等。submit任務時調用的是workQueue的offer方法,而不是put方法,所以並不會block caller。如果保證不丟任務,建議設置爲CallerRunsPolicy,或採用http://stackoverflow.com/questions/2001086/how-to-make-threadpoolexecutors-submit-method-block-if-it-is-saturated的方案,自己重寫RejectedExecutionHandler , 實現BlockPolicy。

2. ExecutorCompletionService的completionQueue是保存結果的,如果worker完成過多且completionQueue沒有及時take, 導致滿了,這時會拋出異常。相關代碼細節參看ExecutorCompletionService.QueueingFuture.done()方法

import java.util.concurrent.*;

public class TestCompletionService {
	public static void main(String[] args){		
		ExecutorService es = Executors.newFixedThreadPool(100);		
		ExecutorCompletionService ecs = new ExecutorCompletionService(es, new LinkedBlockingQueue(2));		
		for(int i=0; i<10; i++){
			final int seq = i;
			ecs.submit(new Callable(){
				public Object call(){
					System.out.println("thread executed" + seq);
					return seq;
				}				
			});
		}		
	}
}

運行拋出異常
Exception in thread "pool-1-thread-2" java.lang.IllegalStateException: Queue full
    at java.util.AbstractQueue.add(Unknown Source)
    at java.util.concurrent.ExecutorCompletionService$QueueingFuture.done(Unknown Source)
    at java.util.concurrent.FutureTask$Sync.innerSet(Unknown Source)
    at java.util.concurrent.FutureTask.set(Unknown Source)
    at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)thread executed5

    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source) 


3. 調動ExecutorService.shutDown() 方法時,workQueue的任務仍會執行。但調用shutDownNow()時,workQueue的任務不會被執行。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章