Runnable runnable = new Runnable(){ public void run(){ System.out.println("Run"); } }
你能夠簡單的在壹個線程中運行它: html
new Thread(runnable).start();
這個代碼很簡潔,可是若是咱們想並行的啓動多個任務該怎麼辦呢,並且咱們還想等待全部任務完成以後獲取全部任務的返回值,這樣的話,要想保持較好的代碼風格實際上有點困難了。不過,就像全部其它的難題壹樣,Java 爲咱們提供了壹個解決方案,那就是 Executor ,這個簡單的類容許你建立線程池和線程工廠。 java
ExecutorService executor = Executors.newFixedThreadPool(5); for (int i = 0; i < 10; i++) { executor.execute(new Runnable() { public void run() { System.out.println("do something here..."); } }); } executor.shutdown();線程池實際表現爲 ExecutorService 類的壹個實例。經過使用 ExecutorService ,你能夠提交將在將來完成的任務。經過 Executor 類你能夠建立以下幾種線程池:
一、Single Thread Executor:只有壹個線程的線程池。因此全部提交的任務都會被順序執行。方法名稱:Executors.newSingleThreadExecutor();
二、Cache Thread Pool:壹個建立足夠多的線程的線程池,能夠並行的執行全部任務。舊的線程會被從新用於新的任務。若是線程在60秒內沒有被用到,這個線程就會被終止而且從線程池中移除掉。方法名稱:Executors.newCachedThreadPool();
三、Fixed Thread Pool:壹個有着固定數量的線程的線程池。若是對於某個任務而言某線程不可用,這個任務會被放進隊列中等待其它的任務完成以後再執行。方法名稱:Executors.newFixedThreadPool();
四、Scheduled Thread Pool:壹個爲定時任務準備的線程池。方法名稱:Executors.newScheduledThreadPool();
五、Single Thread Scheduled Pool:壹個爲定時的將來的任務準備的單個線程的線程池,方法名稱:Executors.newSingleThreadScheduledExecutor();
壹旦你有了壹個線程池,你可使用上述不一樣的提交方法提交你的任務了。你能夠提交壹個 Runnable 或者 Callable 的任務到線程池中。這個方法返回壹個 Future 對象,用於表示這個任務在將來的狀態。若是你提交壹個 Runnable 的任務,那麼壹旦任務結束, Future 將返回 null 。
舉個例子,若是你有以下這樣壹個 Callable 的任務: 算法
private final class StringTask implements Callable<String> { public String call(){ //耗時的操做 return "Run"; } }
若是你但願使用4個線程執行該任務10次,你可使用以下代碼: api
ExecutorService pool = Executors.newFixedThreadPool(4); for(int i = 0; i < 10; i++){ pool.submit(new StringTask()); }可是你必須關閉線程池才能結束池中的全部線程:
pool.shutdown();若是你不這樣作,Java 虛擬機就存在不能關閉的風險,由於仍然有線程沒有終止。如今你可使用 shutdown() 方法強制關閉線程池,可是這樣壹來當前正在執行的任務將會被中斷,而沒有啓動的線程永遠都不會再啓動了。
ExecutorService pool = Executors.newFixedThreadPool(4); List<Future<String>> futures = new ArrayList<Future<String>>(10); for(int i = 0; i < 10; i++){ futures.add(pool.submit(new StringTask())); } for(Future<String> future : futures){ String result = future.get(); //計算結果 } pool.shutdown();可是使用這種代碼略有點複雜,並且有個缺點。若是第壹個任務花了很長時間去計算,而其它任務在它以前先結束了,當前線程在第壹個線程結果以前就不能計算結果。再壹次,Java 爲咱們提供了壹個解決方案,這就是 CompletionService 。
ExecutorService threadPool = Executors.newFixedThreadPool(4); CompletionService<String> pool = new ExecutorCompletionService<String>(threadPool); for(int i = 0; i < 10; i++){ pool.submit(new StringTask()); } for(int i = 0; i < 10; i++){ String result = pool.take().get(); //計算結果 } threadPool.shutdown();經過這種方式,你能夠按照它們完成任務的順序得到結果而沒必要持有壹個全部 Future 對象的集合。
本文英文原文出自 http://www.baptiste-wicht.com/2010/09/java-concurrency-part-7-executors-and-thread-pools/,中文翻譯首發開源中國社區 http://my.oschina.net/bairrfhoinn/blog/167113,轉載請註明原始出處。 併發
2013-10-21 09:54:00 更新:剛剛發現這篇文章的翻譯文章,紅薯已經在以前的討論版塊發過了,連接見於 http://www.oschina.net/question/12_11255 ,貌似我重複造輪子了,汗壹個! oracle