前面幾篇文章分析了線程的主要實現,今天來整體總結以下他們。
總覽圖
直接上總結的總覽圖,如下圖:
如果看過前幾篇文章應該基本能夠看懂這張總結圖,可能在單獨的一篇文章里弄懂了一個知識點,但是沒有一個總體的概念,所以最后有了這種總結圖。前面幾篇文章主要講的就是上圖中AbstractExecutorService、ThreadPoolExecutor、ScheduledThreadPoolExecutor這三個類的主要功能,因為它們是線程池真正的實現者。
兩個接口
接下來詳細解釋下上圖出現的類和接口,首先是最頂層的接口Executor,它只定義了一個方法execute(Runnable command),相當于定義了一個框架,它能夠執行一個任務。Executor就像是定義了一個框架,并確定了這個框架能夠提供的功能。
第二個是ExecutorService接口,它繼承Executor。主要擴展了關閉線程管理的一些功能,比如shutdown方法用來關閉線程池的任務,isTerminated方法來判斷線程池的任務是否結束。
ExecutorService還提供了最重要的方法submit,它支持了有返回結果的任務提交,也引入了實現這個功能最關鍵的接口Callable、Future;
Executor、ExecutorService都是接口,只是定義了提交任務、關閉任務等方法,相當于只是申明了線程池支持這些功能。
AbstractExecutorService
AbstractExecutorService是線程池系列第三個類,它是抽象類并繼承ExecutorService接口。它主要是實現了ExecutorService接口的submit系列方法。
實現submit方法主要依靠RunnableFuture接口和它的實現類FutureTask。RunnableFuture繼承Runnable和Future接口,而它的實現FutureTask的一個屬性callable是Callable類型。
FutureTask實現了Runnable的run方法,run方法調用的是callable的call方法保存執行結果。同時也實現Future的get方法獲取結果,如果任務還沒有執行則阻塞線程。
所以submit方法實現的主要過程是提交的任務Callable封裝成FutureTask,并把FutureTask當作Runnable丟給execute方法去異步執行,然后把FutureTask當作Future作為submit返回值。
但是AbstractExecutorService并沒有實現execute方法,所以它是一個抽象類,在等待有緣人來實現execute,實現線程池的最后一步。
實現正真的實現者ThreadPoolExecutor
ThreadPoolExecutor是Executor框架的正真實現者。它實現了execute方法,execute正真的實現,以下三個關鍵點:
HashSet<Worker> workers;//Worker集合,線程池
BlockingQueue<Runnable> workQueue;//阻塞隊列,要執行的任務
final void runWorker(Worker w);//Worker調用這個方法,可以從阻塞隊列中獲取任務來執行。
這里有一個關鍵類Worker,關鍵源碼如下:
線程池execute方法會先根據現在Worker的數量判斷是創建一個Worker對象還是把任務直接放到隊列中,如果新建了Worker,則在最后會調用Worker的thread的start方法,start方法會異步執行,execute方法就完成了。
start會執行thread的run方法也就會執行Worker的run方法,所以最終會執行線程池的runWorker方法,runWorker會優先執行Worker中保存的任務,如果為null則會從隊列中獲取任務再次執行,獲取不到就阻塞。這里是一個死循環,能拿到任務就執行,執行完就再去拿,拿不到就先阻塞。
延遲隊列
ScheduledExecutorService繼承AbstractExecutorService,它申明了幾個schedule開頭的方法。
而ScheduledThreadPoolExecutor是ScheduledExecutorService的具體實現,通過延遲隊列與線程池實現了定期執行任務的功能。
總結
線程池一直覺得是很復雜的功能,但是分析了它主要的方法的實現后就會發現還是比較簡單的,不過它的實現方式仍然是非常經典巧妙的。
JAVA程序員日常學習筆記,如理解有誤歡迎各位交流討論!