JAVA進階----主線程等待子線程各種方案比較(轉)


創建線程以及管理線程池基本理解 
參考原文鏈接:http://www.oschina.net/question/12_11255?sort=time 

一、創建一個簡單的java線程 
在 Java 語言中,一個最簡單的線程如下代碼所示: 

Java代碼   收藏代碼
  1. Runnable runnable = new Runnable(){  
  2.    public void run(){  
  3.       System.out.println("Run");  
  4.    }  
  5. }  



可通過下面一行代碼來啟動這個線程: 
new Thread(runnable).start(); 
這是一個再簡單不過的例子了,但如果你有許多需要長時間運行的任務同時執行,並需要等所有的這些線程都執行完畢,還想得到一個返回值,那么這就有點小小難度了。但 Java 已經有解決方案給你,那就是 Executors ,一個簡單的類可以讓你創建線程池和線程工廠。 

二、Executors創建線程池 
一個線程池使用類 ExecutorService 的實例來表示,通過 ExecutorService 你可以提交任務,並進行調度執行。下面列舉一些你可以通過 Executors 類來創建的線程池的類型: 

1.Single Thread Executor : 只有一個線程的線程池,因此所有提交的任務是順序執行,代碼:

Java代碼   收藏代碼
  1. Executors.newSingleThreadExecutor()  


2.Cached Thread Pool : 線程池里有很多線程需要同時執行,老的可用線程將被新的任務觸發重新執行,如果線程超過60秒內沒執行,那么將被終止並從池中刪除,代碼:

Java代碼   收藏代碼
  1. Executors.newCachedThreadPool()  


3.Fixed Thread Pool : 擁有固定線程數的線程池,如果沒有任務執行,那么線程會一直等待,代碼:

Java代碼   收藏代碼
  1. Executors.newFixedThreadPool()  


4.Scheduled Thread Pool : 用來調度即將執行的任務的線程池,代碼:

Java代碼   收藏代碼
  1. Executors.newScheduledThreadPool()  


5.Single Thread Scheduled Pool : 只有一個線程,用來調度執行將來的任務,代碼:

Java代碼   收藏代碼
  1. Executors.newSingleThreadScheduledExecutor()  



三、主線程等待子線程結束各種方式 
一旦你創建了一個線程池,你就可以往池中通過不同的方法提交執行任務,可提交 Runnable 或者 Callable 到線程池中,該方法返回一個 Future 實例表示任務的狀態,如果你提交一個 Runnable ,那么如果任務完成后 Future 對象返回 null。 

例如,你編寫下面的 Callable: 

Java代碼   收藏代碼
  1. private final class StringTask extends Callable<String>{  
  2.    public String call(){  
  3.       //Long operations  
  4.    
  5.       return "Run";  
  6.    }  
  7. }  



如果你想使用4個線程來執行這個任務10次,那么代碼如下: 
ExecutorService pool = Executors.newFixedThreadPool(4); 

for(int i = 0; i < 10; i++){ 
   pool.submit(new StringTask()); 


但你必須手工的關閉線程池來結束所有池中的線程: 

pool.shutdown(); 

如果你不這么做,JVM 並不會去關閉這些線程;另外你可以使用 shutdownNow() 的方法來強制關閉線程池,那么執行中的線程也會被中斷,所有尚未被執行的任務也將不會再執行。 

但這個例子中,你無法獲取任務的執行狀態,因此我們需要借助 Future 對象: 

下面的例子同時可以阻塞主線程等待子線程完成,但是該方式,如果阻塞的第一個線程很久,可能其他線程已經執行完了,很多情況不太適用 

Java代碼   收藏代碼
  1. ExecutorService pool = Executors.newFixedThreadPool(4);  
  2.    
  3. List<Future<String>> futures = new ArrayList<Future<String>>(10);  
  4.    
  5. for(int i = 0; i < 10; i++){  
  6.    futures.add(pool.submit(new StringTask()));  
  7. }  
  8.    
  9. for(Future<String> future : futures){  
  10.    String result = future.get();  
  11.    
  12.    //Compute the result  
  13. }  
  14.    
  15. pool.shutdown();  



不過這段代碼稍微有點復雜,而且有不足的地方。如果第一個任務耗費非常長的時間來執行,然后其他的任務都早於它結束,那么當前線程就無法在第一個任務結束之前獲得執行結果,但是別着急,Java 為你提供了解決方案——CompletionService。 

一個 CompletionService 就是一個服務,用以簡化等待任務的執行結果,實現的類是 ExecutorCompletionService,該類基於 ExecutorService,因此我們可試試下面的代碼:
 

Java代碼   收藏代碼
  1. ExecutorService threadPool = Executors.newFixedThreadPool(4);  
  2. CompletionService<String> pool = new ExecutorCompletionService<String>(threadPool);  
  3.    
  4. for(int i = 0; i < 10; i++){  
  5.    pool.submit(new StringTask());  
  6. }  
  7.    
  8. for(int i = 0; i < 10; i++){  
  9.    String result = pool.take().get();  
  10.    
  11.    //Compute the result  
  12. }  
  13.    
  14. threadPool.shutdown();  



通過這段代碼,我們可以根據執行結束的順序獲取對應的結果,而無需維護一個 Future 對象的集合。 
這就是本文的全部,通過 Java 為我們提供的各種工具,可以方便的進行多任務的編程,通過使用 Executors、ExecutorService 以及 CompletionService 等工具類,我們可以創建復雜的並行任務執行算法,而且可以輕松改變線程數。

 

http://825635381.iteye.com/blog/2184605

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM