1. 程式人生 > >java中執行緒池的幾種實現方式

java中執行緒池的幾種實現方式

1、執行緒池簡介:
    多執行緒技術主要解決處理器單元內多個執行緒執行的問題,它可以顯著減少處理器單元的閒置時間,增加處理器單元的吞吐能力。    
    假設一個伺服器完成一項任務所需時間為:T1 建立執行緒時間,T2 線上程中執行任務的時間,T3 銷燬執行緒時間。

    如果:T1 + T3 遠大於 T2,則可以採用執行緒池,以提高伺服器效能。
                一個執行緒池包括以下四個基本組成部分:
                1、執行緒池管理器(ThreadPool):用於建立並管理執行緒池,包括 建立執行緒池,銷燬執行緒池,新增新任務;
                2、工作執行緒(PoolWorker):執行緒池中執行緒,在沒有任務時處於等待狀態,可以迴圈的執行任務;
                3、任務介面(Task):每個任務必須實現的介面,以供工作執行緒排程任務的執行,它主要規定了任務的入口,任務執行完後的收尾工作,任務的執行狀態等;
                4、任務佇列(taskQueue):用於存放沒有處理的任務。提供一種緩衝機制。
                
    執行緒池技術正是關注如何縮短或調整T1,T3時間的技術,從而提高伺服器程式效能的。它把T1,T3分別安排在伺服器程式的啟動和結束的時間段或者一些空閒的時間段,這樣在伺服器程式處理客戶請求時,不會有T1,T3的開銷了。
    執行緒池不僅調整T1,T3產生的時間段,而且它還顯著減少了建立執行緒的數目,看一個例子:
    假設一個伺服器一天要處理50000個請求,並且每個請求需要一個單獨的執行緒完成。線上程池中,執行緒數一般是固定的,所以產生執行緒總數不會超過執行緒池中執行緒的數目,而如果伺服器不利用執行緒池來處理這些請求則執行緒總數為50000。一般執行緒池大小是遠小於50000。所以利用執行緒池的伺服器程式不會為了建立50000而在處理請求時浪費時間,從而提高效率。

    程式碼實現中並沒有實現任務介面,而是把Runnable物件加入到執行緒池管理器(ThreadPool),然後剩下的事情就由執行緒池管理器(ThreadPool)來完成了

  1. package mine.util.thread;  
  2. import java.util.LinkedList;  
  3. import java.util.List;  
  4. /** 
  5.  * 執行緒池類,執行緒管理器:建立執行緒,執行任務,銷燬執行緒,獲取執行緒基本資訊 
  6.  */
  7. publicfinalclass ThreadPool {  
  8.     // 執行緒池中預設執行緒的個數為5
  9.     privatestaticint worker_num = 5;  
  10.     // 工作執行緒
  11.     private WorkThread[] workThrads;  
  12.     // 未處理的任務
  13.     privatestaticvolatileint finished_task = 0;  
  14.     // 任務佇列,作為一個緩衝,List執行緒不安全
  15.     private List<Runnable> taskQueue = new LinkedList<Runnable>();  
  16.     privatestatic ThreadPool threadPool;  
  17.     // 建立具有預設執行緒個數的執行緒池
  18.     private ThreadPool() {  
  19.         this(5);  
  20.     }  
  21.     // 建立執行緒池,worker_num為執行緒池中工作執行緒的個數
  22.     private ThreadPool(int worker_num) {  
  23.         ThreadPool.worker_num = worker_num;  
  24.         workThrads = new WorkThread[worker_num];  
  25.         for (int i = 0; i < worker_num; i++) {  
  26.             workThrads[i] = new WorkThread();  
  27.             workThrads[i].start();// 開啟執行緒池中的執行緒
  28.         }  
  29.     }  
  30.     // 單態模式,獲得一個預設執行緒個數的執行緒池
  31.     publicstatic ThreadPool getThreadPool() {  
  32.         return getThreadPool(ThreadPool.worker_num);  
  33.     }  
  34.     // 單態模式,獲得一個指定執行緒個數的執行緒池,worker_num(>0)為執行緒池中工作執行緒的個數
  35.     // worker_num<=0建立預設的工作執行緒個數
  36.     publicstatic ThreadPool getThreadPool(int worker_num1) {  
  37.         if (worker_num1 <= 0)  
  38.             worker_num1 = ThreadPool.worker_num;  
  39.         if (threadPool == null)  
  40.             threadPool = new ThreadPool(worker_num1);  
  41.         return threadPool;  
  42.     }  
  43.     // 執行任務,其實只是把任務加入任務佇列,什麼時候執行有執行緒池管理器覺定
  44.     publicvoid execute(Runnable task) {  
  45.         synchronized (taskQueue) {  
  46.             taskQueue.add(task);  
  47.             taskQueue.notify();  
  48.         }  
  49.     }  
  50.     // 批量執行任務,其實只是把任務加入任務佇列,什麼時候執行有執行緒池管理器覺定
  51.     publicvoid execute(Runnable[] task) {  
  52.         synchronized (taskQueue) {  
  53.             for (Runnable t : task)  
  54.                 taskQueue.add(t);  
  55.             taskQueue.notify();  
  56.         }  
  57.     }  
  58.     // 批量執行任務,其實只是把任務加入任務佇列,什麼時候執行有執行緒池管理器覺定
  59.     publicvoid execute(List<Runnable> task) {  
  60.         synchronized (taskQueue) {  
  61.             for (Runnable t : task)  
  62.                 taskQueue.add(t);  
  63.             taskQueue.notify();  
  64.         }  
  65.     }  
  66.     // 銷燬執行緒池,該方法保證在所有任務都完成的情況下才銷燬所有執行緒,否則等待任務完成才銷燬
  67.     publicvoid destroy() {  
  68.         while (!taskQueue.isEmpty()) {// 如果還有任務沒執行完成,就先睡會吧
  69.             try {  
  70.                 Thread.sleep(10);  
  71.             } catch (InterruptedException e) {  
  72.                 e.printStackTrace();  
  73.             }  
  74.         }  
  75.         // 工作執行緒停止工作,且置為null
  76.         for (int i = 0; i < worker_num; i++) {  
  77.             workThrads[i].stopWorker();  
  78.             workThrads[i] = null;  
  79.         }  
  80.         threadPool=null;  
  81.         taskQueue.clear();// 清空任務佇列
  82.     }  
  83.     // 返回工作執行緒的個數
  84.     publicint getWorkThreadNumber() {  
  85.         return worker_num;  
  86.     }  
  87.     // 返回已完成任務的個數,這裡的已完成是隻出了任務佇列的任務個數,可能該任務並沒有實際執行完成
  88.     publicint getFinishedTasknumber() {  
  89.         return finished_task;  
  90.     }  
  91.     // 返回任務佇列的長度,即還沒處理的任務個數
  92.     publicint getWaitTasknumber() {  
  93.         return taskQueue.size();  
  94.     }  
  95.     // 覆蓋toString方法,返回執行緒池資訊:工作執行緒個數和已完成任務個數
  96.     @Override
  97.     public String toString() {  
  98.         return"WorkThread number:" + worker_num + "  finished task number:"
  99.                 + finished_task + "  wait task number:" + getWaitTasknumber();  
  100.     }  
  101.     /** 
  102.      * 內部類,工作執行緒 
  103.      */
  104.     privateclass WorkThread extends