Java線程(六)----線程池

 自JDK5之後,Java推出了一個併發包,java.util.concurrent,在Java開發中,我們接觸到了好多池的技術,String類的對象池、Integer的共享池、連接數據庫的連接池、Struts1.3的對象池等等,池的最終目的都是節約資源,以更小的開銷做更多的事情,從而提高性能。

        我們的web項目都是部署在服務器上,瀏覽器端的每一個request就是一個線程,那麼服務器需要併發的處理多個請求,就需要線程池技術,下面來看一下Java併發包下如何創建線程池。

        1.  創建一個可重用固定線程集合的線程池,以共享的無界隊列方式來運行這些線程。

  1. ExecutorService threadPool = Executors.newFixedThreadPool(3);// 創建可以容納3個線程的線程池  
        2. 創建一個可根據需要創建新線程的線程池,但是在以前構造的線程可用時將重用它們。

  1. ExecutorService threadPool = Executors.newCachedThreadPool();// 線程池的大小會根據執行的任務數動態分配  
        3. 創建一個使用單個 worker 線程的 Executor,以無界隊列方式來運行該線程。

  1. ExecutorService threadPool = Executors.newSingleThreadExecutor();// 創建單個線程的線程池,如果當前線程在執行任務時突然中斷,則會創建一個新的線程替代它繼續執行任務  

        4. 創建一個可安排在給定延遲後運行命令或者定期地執行的線程池。

  1. ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(3);// 效果類似於Timer定時器  
        每種線程池都有不同的使用場景,下面看一下這四種線程池使用起來有什麼不同。

        1. FixedThreadPool

  1. import java.util.concurrent.ExecutorService;  
  2. import java.util.concurrent.Executors;  
  3. public class ThreadPoolTest {  
  4.     public static void main(String[] args) {  
  5.         ExecutorService threadPool = Executors.newFixedThreadPool(3);  
  6.         for(int i = 1; i < 5; i++) {  
  7.             final int taskID = i;  
  8.             threadPool.execute(new Runnable() {  
  9.                 public void run() {  
  10.                     for(int i = 1; i < 5; i++) {  
  11.                         try {  
  12.                             Thread.sleep(20);// 爲了測試出效果,讓每次任務執行都需要一定時間  
  13.                         } catch (InterruptedException e) {  
  14.                             e.printStackTrace();  
  15.                         }  
  16.                         System.out.println("第" + taskID + "次任務的第" + i + "次執行");  
  17.                     }  
  18.                 }  
  19.             });  
  20.         }  
  21.         threadPool.shutdown();// 任務執行完畢,關閉線程池  
  22.     }  
  23. }  
        輸出結果:

  1. 1次任務的第1次執行  
  2. 2次任務的第1次執行  
  3. 3次任務的第1次執行  
  4. 2次任務的第2次執行  
  5. 3次任務的第2次執行  
  6. 1次任務的第2次執行  
  7. 3次任務的第3次執行  
  8. 1次任務的第3次執行  
  9. 2次任務的第3次執行  
  10. 3次任務的第4次執行  
  11. 2次任務的第4次執行  
  12. 1次任務的第4次執行  
  13. 4次任務的第1次執行  
  14. 4次任務的第2次執行  
  15. 4次任務的第3次執行  
  16. 4次任務的第4次執行  
        上段代碼中,創建了一個固定大小的線程池,容量爲3,然後循環執行了4個任務,由輸出結果可以看到,前3個任務首先執行完,然後空閒下來的線程去執行第4個任務,在FixedThreadPool中,有一個固定大小的池,如果當前需要執行的任務超過了池大小,那麼多於的任務等待狀態,直到有空閒下來的線程執行任務,而當執行的任務小於池大小,空閒的線程也不會去銷燬。
        2. CachedThreadPool

        上段代碼其它地方不變,將newFixedThreadPool方法換成newCachedThreadPool方法。

        輸出結果:

  1. 3次任務的第1次執行  
  2. 4次任務的第1次執行  
  3. 1次任務的第1次執行  
  4. 2次任務的第1次執行  
  5. 4次任務的第2次執行  
  6. 3次任務的第2次執行  
  7. 2次任務的第2次執行  
  8. 1次任務的第2次執行  
  9. 2次任務的第3次執行  
  10. 3次任務的第3次執行  
  11. 1次任務的第3次執行  
  12. 4次任務的第3次執行  
  13. 2次任務的第4次執行  
  14. 4次任務的第4次執行  
  15. 3次任務的第4次執行  
  16. 1次任務的第4次執行  
        可見,4個任務是交替執行的,CachedThreadPool會創建一個緩存區,將初始化的線程緩存起來,如果線程有可用的,就使用之前創建好的線程,如果沒有可用的,就新創建線程,終止並且從緩存中移除已有60秒未被使用的線程。

        3. SingleThreadExecutor        

       上段代碼其它地方不變,將newFixedThreadPool方法換成newSingleThreadExecutor方法。       

       輸出結果:

  1. 1次任務的第1次執行  
  2. 1次任務的第2次執行  
  3. 1次任務的第3次執行  
  4. 1次任務的第4次執行  
  5. 2次任務的第1次執行  
  6. 2次任務的第2次執行  
  7. 2次任務的第3次執行  
  8. 2次任務的第4次執行  
  9. 3次任務的第1次執行  
  10. 3次任務的第2次執行  
  11. 3次任務的第3次執行  
  12. 3次任務的第4次執行  
  13. 4次任務的第1次執行  
  14. 4次任務的第2次執行  
  15. 4次任務的第3次執行  
  16. 4次任務的第4次執行  
        4個任務是順序執行的,SingleThreadExecutor得到的是一個單個的線程,這個線程會保證你的任務執行完成,如果當前線程意外終止,會創建一個新線程繼續執行任務,這和我們直接創建線程不同,也和newFixedThreadPool(1)不同。

    4.ScheduledThreadPool    

  1. import java.util.concurrent.ScheduledExecutorService;  
  2. import java.util.concurrent.TimeUnit;  
  3. public class ThreadPoolTest {  
  4.     public static void main(String[] args) {  
  5.         ScheduledExecutorService schedulePool = Executors.newScheduledThreadPool(1);  
  6.         // 5秒後執行任務  
  7.         schedulePool.schedule(new Runnable() {  
  8.             public void run() {  
  9.                 System.out.println("爆炸");  
  10.             }  
  11.         }, 5, TimeUnit.SECONDS);  
  12.         // 5秒後執行任務,以後每2秒執行一次  
  13.         schedulePool.scheduleAtFixedRate(new Runnable() {  
  14.             @Override  
  15.             public void run() {  
  16.                 System.out.println("爆炸");  
  17.             }  
  18.         }, 52, TimeUnit.SECONDS);  
  19.     }  
  20. }  
        ScheduledThreadPool可以定時的或延時的執行任務。

        Java的併發包很強大,上面所說只是入門,隨着學習深入,會有更多記錄在博客裏

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