這一節主要講線程池ThreadPoolExecutor類中的execute方法,了解線程池的執行原理。
首先我們要明白不論是execute還是submit最終都是調用execute所有我們只需要了解execute源碼就可以。
首先我們來明確一點:int c = ctl.get();其實拿到的是一個數字,這個數字是通過&運算得到的結果,這個數字里面包含了兩點比較重要的數據信息第一:通過這個數字可以得到線程的狀態,第二:通過這個數字可以當前線程池中線程的數量。至于怎么計算得到我們先不做考慮(我也不是很清楚)
因此我們知道第一個if判斷的是當前線程池的線程數和核心線程數大小關系,如果小于核心線程數就直接將當前任務加入線程池。因此我們來看看addWorker(command,true)具體內容是什么。
首先是一個永真循環,拿到線程池的數量和線程池的狀態做一次有效性的判斷,接著又是一個永真的循環,判斷線程池的數量,并且嘗試將線程池的數量加1,成功之后退出。總結起來就是:對線程池數量狀態做一些校驗,然后不斷嘗試給線程池數量加1,退出條件要么校驗失敗,要么加1成功。
由于之前的代碼已經給線程池的數量加1了所有這段代碼的主要目的是把這個線程或者說任務添加到線程池里也就是hashset里。
首先會有一個加鎖的操作保證原子性,然后就是判斷線程池的狀態和線程池的數量,如果沒有問題的話就加入hashset里,并且要把當前加入的線程或者任務啟動;如果加入失敗的話就需要看看加入失敗的代碼了。
加入失敗的話也很好理解:首先我們需要把這個線程從set里面移除,其次我們需要把之前線程池里面加1的數量減掉,還有一點比較特殊的就是我們需要嘗試終止線程池。
好了現在拉回到我們最初的地方,這只是我們判斷線程池中數量小于核心線程數的情況
如果要是大于核心線程數量的話我們需要添加到阻塞隊列的,這個很簡單直接添加就可以不過在添加完了是需要再次check的
如果不滿足以上兩種情況的話我們就需要嘗試新建線程添加任務,如果失敗的話就調用相應的拒絕策略就可以。
好了本節就主要講解execute方法,相對來說線程池的執行還是比較好理解。