以前記的筆記。
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方法。
- //將command放入線程池等待以及執行。
- /**
- * Arrange for the given command to be executed by a thread in this
- * pool. The method normally returns when the command has been
- * handed off for (possibly later) execution.
- **/
- public void execute(Runnable command) throws InterruptedException {
- for (;;) {
- synchronized(this) {
- if (!shutdown_) {
- int size = poolSize_;
- // 如果工作線程沒有到達指定配置數則增加。
- // addThread將會增加W-T對,並把command直接給他作爲第一個command運行。
- // Ensure minimum number of threads
- if (size < minimumPoolSize_) {
- addThread(command);
- return;
- }
- // 向Channel中存入command,並且不等待。
- // 如果沒有得到則,返回false。並且進入下一次循環(無限)或增加工作線程W-T。
- //
- // Try to give to existing thread
- if (handOff_.offer(command, 0)) {
- return;
- }
- // 如果是工作線程不夠,則增加W-T並執行command。
- // If cannot handoff and still under maximum, create new thread
- if (size < maximumPoolSize_) {
- addThread(command);
- return;
- }
- }
- }
- // 每次循環都執行BlockedExecutionHandler這個block Hook。
- // 默認行爲是由調用execute的線程自己來執行command。
- // Cannot hand off and cannot create -- ask for help
- if (getBlockedExecutionHandler().blockedAction(command)) {
- return;
- }
- }//for
- }
worker 的工作
- /**
- * Class defining the basic run loop for pooled threads.
- **/
- protected class Worker implements Runnable {
- protected Runnable firstTask_;
- protected Worker(Runnable firstTask) { firstTask_ = firstTask; }
- public void run() {
- try {
- // 如果有默認的第一個command則執行它
- Runnable task = firstTask_;
- firstTask_ = null; // enable GC
- if (task != null) {
- task.run();
- task = null;
- }
- // 不斷使用getTask()來獲取 command (其實就是不斷從Channel中取)。
- // 執行command
- while ( (task = getTask()) != null) {
- task.run();
- task = null;
- }
- }
- catch (InterruptedException ex) { } // fall through
- finally {
- // 結束時 執行
- workerDone(this);
- }
- }
- }
getTask是比較奧妙的地方。
- /**
- * Get a task from the handoff queue, or null if shutting down.
- **/
- protected Runnable getTask() throws InterruptedException {
- long waitTime;
- synchronized(this) {
- if (poolSize_ > maximumPoolSize_) // Cause to die if too many threads
- return null;
- waitTime = (shutdown_)? 0 : keepAliveTime_;
- }
- if (waitTime >= 0)
- return (Runnable)(handOff_.poll(waitTime));
- else
- return (Runnable)(handOff_.take());
- }