PooledExecutor 研究(第三方包,當時還沒有用jdk5)

 
以前記的筆記。

PooledExecutor基本以一個Channel以及一組Worker-Thread對組成。

Channel負責緩存目標請求(目標請求也是Runable接口的實現)以及“存”“取”。Channel是一個可以阻塞的Queue,他有4個 方法。其中offer put 方法用來放入元素。poll take方法來獲取數據。offer以及poll方法都是可以設定超時的阻塞方法。一旦超時則會將不再等待,並返回false。 PooledExecutor主要使用0等待的的offer以及poll。

每一組W-T中的W(Runable的實現)成爲目標請求的代理執行者,由T來負責真正啓動執行。而執行的時候是由T來驅動其內部的W進行工作的。在一組W-T中Worker作爲key、Thread作爲value,形成字典形式。

工作基本流程基本如下:T中的W不斷的從Channel中取請求(command 也應該是Runable的實現)。如果沒有請求,則等待或結束自己的運行。而每次放入請求時,都會檢查(根據最大最小值的設定)是否需要多生成一個W-T 對(PooledExecutor.addThread()方法);如果不需要則會直接放入Channel(Channel.offer方法);如果需要 則會生成,並直接把自己給新生成的W。






元代碼分析與註釋: execute方法。

  1.  //將command放入線程池等待以及執行。
  2.   /**
  3.    * Arrange for the given command to be executed by a thread in this
  4.    * pool.  The method normally returns when the command has been
  5.    * handed off for (possibly later) execution.
  6.    **/
  7.   public void execute(Runnable command) throws InterruptedException {
  8.     for (;;) { 
  9.       synchronized(this) { 
  10.         if (!shutdown_) {
  11.           int size = poolSize_;
  12.           // 如果工作線程沒有到達指定配置數則增加。
  13.           // addThread將會增加W-T對,並把command直接給他作爲第一個command運行。
  14.           // Ensure minimum number of threads
  15.           if (size < minimumPoolSize_) {
  16.             addThread(command);
  17.             return;
  18.           }
  19.           
  20.           // 向Channel中存入command,並且不等待。
  21.           // 如果沒有得到則,返回false。並且進入下一次循環(無限)或增加工作線程W-T。
  22.           // 
  23.           // Try to give to existing thread
  24.           if (handOff_.offer(command, 0)) { 
  25.             return;
  26.           }
  27.           
  28.           // 如果是工作線程不夠,則增加W-T並執行command。
  29.           // If cannot handoff and still under maximum, create new thread
  30.           if (size < maximumPoolSize_) {
  31.             addThread(command);
  32.             return;
  33.           }
  34.         }
  35.       }
  36.       // 每次循環都執行BlockedExecutionHandler這個block Hook。
  37.       // 默認行爲是由調用execute的線程自己來執行command。
  38.       // Cannot hand off and cannot create -- ask for help
  39.       if (getBlockedExecutionHandler().blockedAction(command)) {
  40.         return;
  41.       }
  42.     }//for
  43.   }


worker 的工作

  1.   /**
  2.    * Class defining the basic run loop for pooled threads.
  3.    **/
  4.   protected class Worker implements Runnable {
  5.     protected Runnable firstTask_;
  6.     protected Worker(Runnable firstTask) { firstTask_ = firstTask; }
  7.     public void run() {
  8.       try {
  9.         // 如果有默認的第一個command則執行它
  10.         Runnable task = firstTask_;
  11.         firstTask_ = null// enable GC
  12.         if (task != null) {
  13.           task.run();
  14.           task = null;
  15.         }
  16.         // 不斷使用getTask()來獲取 command (其實就是不斷從Channel中取)。
  17.         // 執行command
  18.         while ( (task = getTask()) != null) {
  19.           task.run();
  20.           task = null;
  21.         }
  22.       }
  23.       catch (InterruptedException ex) { } // fall through
  24.       finally {
  25.         // 結束時 執行
  26.         workerDone(this);
  27.       }
  28.     }
  29.   }


getTask是比較奧妙的地方。


  1.   /** 
  2.    * Get a task from the handoff queue, or null if shutting down.
  3.    **/
  4.   protected Runnable getTask() throws InterruptedException {
  5.     long waitTime;
  6.     synchronized(this) {
  7.       if (poolSize_ > maximumPoolSize_) // Cause to die if too many threads
  8.         return null;
  9.       waitTime = (shutdown_)? 0 : keepAliveTime_;
  10.     }
  11.     if (waitTime >= 0
  12.       return (Runnable)(handOff_.poll(waitTime));
  13.     else 
  14.       return (Runnable)(handOff_.take());
  15.   }




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