1. 程式人生 > >多執行緒技術原理

多執行緒技術原理

首先是其繼承關係如下:


通過觀察上面四種執行緒池的原始碼:

如:newFixedThreadPool

  1. publicstatic ExecutorService newFixedThreadPool(int nThreads) {  
  2.     returnnew ThreadPoolExecutor(nThreads, nThreads,  
  3.                                   0L, TimeUnit.MILLISECONDS,  
  4.                                   new LinkedBlockingQueue<Runnable>());  
  5. }  
如:newCachedThreadPool
  1. publicstatic ExecutorService newCachedThreadPool() {  
  2.     returnnew ThreadPoolExecutor(0, Integer.MAX_VALUE,  
  3.                                   60L, TimeUnit.SECONDS,  
  4.                                   new SynchronousQueue<Runnable>());  
  5. }  
如:newSingleThreadExecutor
  1. public
    static ExecutorService newSingleThreadExecutor() {  
  2.     returnnew FinalizableDelegatedExecutorService  
  3.         (new ThreadPoolExecutor(11,  
  4.                                 0L, TimeUnit.MILLISECONDS,  
  5.                                 new LinkedBlockingQueue<Runnable>()));  
  6. }  

可以發現,其實它們呼叫的都是同一個介面ThreadPoolExecutor方法,只不過傳入引數不一樣而已。下面就來看看這個神祕的ThreadPoolExecutor。
首先來看看它的一些基本引數:

  1. publicclass ThreadPoolExecutor extends AbstractExecutorService {  
  2.     //執行狀態標誌位
  3.     volatileint runState;  
  4.     staticfinalint RUNNING    = 0;  
  5.     staticfinalint SHUTDOWN   = 1;  
  6.     staticfinalint STOP       = 2;  
  7.     staticfinalint TERMINATED = 3;  
  8.     //執行緒緩衝佇列,當執行緒池執行緒執行超過一定執行緒時並滿足一定的條件,待執行的執行緒會放入到這個佇列
  9.     privatefinal BlockingQueue<Runnable> workQueue;  
  10.     //重入鎖,更新核心執行緒池大小、最大執行緒池大小時要加鎖
  11.     privatefinal ReentrantLock mainLock = new ReentrantLock();  
  12.     //重入鎖狀態
  13.     privatefinal Condition termination = mainLock.newCondition();  
  14.     //工作都set集合
  15.     privatefinal HashSet<Worker> workers = new HashSet<Worker>();  
  16.     //執行緒執行完成後線上程池中的快取時間
  17.     privatevolatilelong  keepAliveTime;  
  18.     //核心執行緒池大小 
  19.     privatevolatileint   corePoolSize;  
  20.     //最大執行緒池大小 
  21.     privatevolatileint   maximumPoolSize;  
  22.     //當前執行緒池在執行執行緒大小 
  23.     privatevolatileint   poolSize;  
  24.     //當緩衝佇列也放不下執行緒時的拒絕策略
  25.     privatevolatile RejectedExecutionHandler handler;  
  26.     //執行緒工廠,用來建立執行緒
  27.     privatevolatile ThreadFactory threadFactory;     
  28.     //用來記錄執行緒池中曾經出現過的最大執行緒數
  29.     privateint largestPoolSize;     
  30.    //用來記錄已經執行完畢的任務個數
  31.    privatelong completedTaskCount;     
  32.     ................  
  33. }  

初始化執行緒池大小 有以下四種方法:

從原始碼中可以看到其實最終都是呼叫了以下的方法:

  1. public ThreadPoolExecutor(int corePoolSize,  
  2.                           int maximumPoolSize,  
  3.                           long keepAliveTime,  
  4.                           TimeUnit unit,  
  5.                           BlockingQueue<Runnable> workQueue,  
  6.                           ThreadFactory threadFactory,  
  7.                           RejectedExecutionHandler handler) {  
  8.     if (corePoolSize < 0 ||  
  9.         maximumPoolSize <= 0 ||  
  10.         maximumPoolSize < corePoolSize ||  
  11.         keepAliveTime < 0)  
  12.         thrownew IllegalArgumentException();  
  13.     if (workQueue == null || threadFactory == null || handler == null)  
  14.         thrownew NullPointerException();  
  15.     this.corePoolSize = corePoolSize;  
  16.     this.maximumPoolSize = maximumPoolSize;  
  17.     this.workQueue = workQueue;  
  18.     this.keepAliveTime = unit.toNanos(keepAliveTime);  
  19.     this.threadFactory = threadFactory;  
  20.     this.handler = handler;  
  21. }  
這裡很簡單,就是設定一下各個引數,並校驗引數是否正確,然後丟擲對應的異常。

接下來我們來看看最重要的方法execute,其原始碼如下:

  1. publicvoid execute(Runnable command) {  
  2.     if (command == null)  
  3.         thrownew NullPointerException();  
  4.     if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) { //  判斷1
  5.         if (runState == RUNNING && workQueue.offer(command)) { // 判斷2
  6.             if (runState != RUNNING || poolSize == 0)  //  判斷3
  7.                 ensureQueuedTaskHandled(command);  
  8.         }  
  9.         elseif