JDK1.5之前,我們如果想要使用Java線程來完成相關任務,一般涉及兩個類,一個是Thread類,一個Thread對象在啟動(start)之後會創建一個關聯的本地操作系統線程,隨後會自動回調run方法。另一個是Runnable接口,可以看作 run方法的抽象,代表線程任務。通過Runnable和Thread的配合可以編寫我們自己的多線程邏輯。
可以看到,此時Java對於多線程編程的支持還是比較原始的,功能也並不多。因此,在JDK1.5的JUC包中,對Java的多線程應用做了一次全面的擴展,比如新lock鎖、併發容器等,還有一個重要的擴展就是出現了Executor執行框架。
Executor執行框架將Java線程的應用做了更細緻的功能劃分,並且進行了功能的增強,大概包括三個部分:
線程任務
JDK1.5之前,只有Runnable代表線程任務,對於受檢異常,必須手動在try catch中處理,不支持throws聲明可能拋出的異常,不支持任務返回值。
JDK1.5的時候,出現了Callable接口,可以看作Runnable的增強:對於受檢異常,可以不用在try catch中處理,支持throws聲明可能拋出的異常,並且支持任務返回值。
執行器
JDK1.5之前,線程任務的執行需要我們手動創建Thread對象、傳入任務、並調用start方法,一個任務對應一個線程,它們之間的關聯非常緊密,這樣對於線程任務的管理、線程資源的複用等功能幾乎沒有,或者只能自己手動實現,非常麻煩。
JDK1.5的時候,出現了Executor線程池。線程池作為任務執行器,我們只需要創建指定的線程池,隨後將線程任務傳入線程池中,由線程池來確定是將任務直接分配給池中的線程去執行、還是創建線程並執行、或者是加入任務隊列等待等等邏輯,使用線程池之後我們不再需要手動創建線程去執行,並且可以實現線程的複用以及線程任務的管理等強大的功能。執行器(線程池)將任務與線程解耦!
異步執行結果
JDK1.5之前,在線程任務啟動之後,對於線程任務監控幾乎沒有,我們不知道任務有沒有完成,也沒辦法定義任務的返回值等一系列信息。
JDK1.5的時候,出現了Future接口以及它的各種實現。這個接口體系代表了線程任務異步計算的結果,通常與Callable線程任務連用。利用了Future設計模式,在一個線程A執行線程任務的時候,我麼可以在另一個線程B中異步的通過Future的實現的相關方法完成判斷對應線程任務是否執行完畢、是否被取消、手動取消正在執行的線程任務、以及從執行完畢的線程任務中獲取返回值等功能。
有了執行框架,我們只需創建線程任務、然後交給指定的線程池去執行,執行完畢之後等待獲取返回結果即可,不再需要關注線程的創建、開啟、執行、回收等基礎性的中間工作,將任務與線程解耦,程序員更加的關注線程任務本身(這裡是和業務相關的),有利於多線程程序的開發!
如果想要使用執行框架,只需要看相關api文檔即可!那麼我們有必要深入理解執行框架嗎?當然時間充足的情況下是有必要的,只有我們知道了執行框架的原理之後,才能更好的使用它。執行框架屬於JDK自帶的基礎框架,經歷了時間和眾多Java開發者的考驗,不求能夠手寫,僅僅學習它的設計精華,包括各種設計模式,同時避開隱藏的坑,對於程序員個人的後續職業發展也是具有很大幫助的!
線程任務、執行器、執行結果這三部分,都可以圍繞著Executor線程池展開,因此下面我們將從Executor入手,並且會穿插介紹Callable和Future的相關原理。
本文來源於:奈學開發者社區,如有侵權,請聯繫我刪除~