在Executors
中提供了四種線程池:segmentfault
newCachedThreadPool
可緩存線程池,對於每一個線程,若是有空閒線程可用,當即讓它執行,若是沒有,則建立一個新線程newFixedThreadPool
具備固定大小的線程池,若是任務數大於空閒的線程數,則把它們放進隊列中等待newSingleThreadPool
大小爲1的線程池,任務一個接着一個完成newScheduledThreadPool
定長線程池,可控制線程最大併發數,支持定時及週期性任務執行,用來代替Timer在上文http://segmentfault.com/a/1190000003091174 中說到了callable不能直接被Thread運行,但卻能被線程池運行,ExecutorService
提供了幾種方法運行一個任務:緩存
Future submit(Callable task);
Future submit(Runnable task, T result);
Future submit(Runnable task);併發
第一個方法能夠直接提交一個Callable任務,返回一個包含結果的Future<T>
,第二個方法會返回指定的result對象,第三個方法返回一個Future<?>
,可使用這樣的對象來調用isDone
,cancel
,isCancelled
,可是在get的時候返回null。線程
此外,有兩個經常使用的關閉線程池的方法:code
void shutdown();
List<Runnable> shutdownNow()對象
第一個方法將啓動一次順序關閉,有任務在執行,則等待執行完成,但不接受新的任務;
第二個方法將取消全部未開始的任務而且試圖中斷正在執行的任務,返回從未開始執行的任務的列表。沒法保證可以中止正在處理的活動執行任務,可是會盡力嘗試。例如,經過 Thread.interrupt()
來取消典型的實現,因此任何任務沒法響應中斷均可能永遠沒法終止。隊列
ExecutorService
提供了invokeAny
和invokeAll
方法,它們是批量執行的最經常使用形式,它們執行任務collection,而後等待至少一個,或所有任務完成get
/** 執行給定的任務,當全部任務完成時,返回保持任務狀態和結果的 Future 列表。返回列表的全部元素的 Future.isDone() 爲 true。 注意,能夠正常地或經過拋出異常來終止已完成任務。 **/ <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException /** 執行給定的任務,若是其中一個任務的結果。一旦正常或異常返回後,則取消還沒有完成的任務。 **/ <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException
invokeAny
方法提交全部任務到一個Callable
對象的集合中,而且返回某個已經完成了的任務的結果,返回的任務是不肯定的。invokeAll
方法則返回全部任務的結果,能夠這樣來對結果進行處理:it
List<Callable<T>> tasks=... List<Future<T>> results = executor.invokeAll(tasks); for(Future<T> result : results){ process(result.get()); } ...
這樣處理的一個弊端是,若是第一個任務花費了很長時間,則不得不等待。在某些狀況下,可能只須要一個任務出告終果就能夠停止全部任務,這樣就得不償失。將結果按照可得到的順序保存起來可能更好,這時須要用到ExecutorCompletionService
來進行排列:io
ExecutorCompletionService service = new ExecutorCompletionService(executor); for(Callable<T> task:tasks){ service.submit(task); } for(int i = 0;i < task.size();i++){ process(service.take().get()); } ...
其中,take()
方法會移除下一個已經完成的結果(Future
),若是沒有可用結果則阻塞
在使用線程池時,大多應該按照如下步驟:
Executors
類中的靜態方法newCachedThreadPool
或newFixedThreadPool
建立線程池;submit
提交Runnable
或Callable
任務;Callable
對象,那就要保存好返回的Future
對象;shutdown