線程池_02_Executor框架

線程池_02_Executor框架
線程池_02_Executor框架
  • 一、Executor 的兩級調度
    • 背景知識
      • 在HotSpot Vm 的線程模型中,Java 線程被一對一映射爲本地操作系統線程。Java 線程啓動時會創建一個本地操作系統線程;當該Java線程終止時,這個操作系統線程也會被回收。
    • Executor
      • 在上層,Java多線程程序通常把應用分解爲若干個任務,然後使用用戶級的調度器(Executor框架)將這些任務映射爲固定數量的線程;換句話說就是應用程序通過Executor框架控制上層的調度。
      • 在底層,操作系統內核將這些線程映射到硬件處理器上。換句話說,下層的調度由操作系統內核控制,下層的調度不受應用程序的控制。
  • 二、Executor 的組成
    • 1、任務;
      • 包括被執行任務需要實現的接口:Runbable或Callable 接口
    • 2、任務的執行;
      • 包括任務執行機制的核心接口Executor,以及繼承自Executor 的ExecutorService接口。Executor 框架有兩個關鍵類實現了ExecutorService 接口
    • 3、異步計算的結果;
      • 包括接口Future 和 實現Future接口的FutureTask類。
  • 三、Executor 使用
    • 1、主線程首先創建Runnable或Callable的任務對象A;
    • 2、然後把對象A直接交給ExecutorService通過Execute或Submit方法執行;
    • 3、如果使用的是submit方法,會返回一個實現Future接口的對象,主線程可以執行FutureTask.get()方法來等待任務執行完成。也可以執行FutureTask.cancle()來取消任務。
  • 四、Executor 主要的類與接口的簡介
    • 1、Executor
      • 接口,是Executor框架的基礎,它將任務的提交與任務的執行分離開來。
    • 2、ThreadPoolExecutor
      • 線程池的核心實現類,用來執行被提交的任務
    • 3、ScheduledThreadPoolExecutor(定時任務類,這裏不討論)
      • 實現類,可以在給定的延遲後運行命令,或者定期執行命令。
    • 4、Future接口和實現Future接口的FutureTask類,代表異步結算的結果
    • 5、Runnable 和Callable接口的實現類
  • 五、Executor 主要的類與接口的詳解
    • ThreadPoolExecutor
      • 四個核心參數:
        • 1、corePool 核心線程池的大小;
        • 2、maximumPool 最大線程池的大小;
        • 3、BlockingQueue 用來暫時保存任務的工作隊列;
        • 4、RejectedExecutionHandler 當ThreadPoolExecutor 可以關閉或ThreadExecutor 已經飽和時(達到了最大線程池大小並且工作隊列已滿),execute()方法將要調用的Handler。
      • ThreadPoolExecutor通常使用工廠類Executors來創建,Executors可以創建3種類型的ThreadPoolExecutor: FixedThreadPool、SingleThreadExecutor、CachedThreadPool;
        • 1、FixedThreadPool ,創建固定線程數的API。
          • 創建的方法:
            • FixedThreadPool 的核心線程和最大線程數是一樣的;線程的空閒存活時間爲0,則多餘的空閒線程會被立即終止。
          • 執行execute(),流程如下:
            • 1、如果當前運行的線程數少於corePoolSize,則創建新線程來執行任務;
            • 2、如果當前運行的線程數等於corePoolSize,將任務加入LinkedBlockingQueue;
            • 3、線程執行完1中的任務後,會在循環中反覆從LinkedBlockingQueue獲取任務來執行。
          • 使用無界隊列LinkedBlockingQueue,影響:
            • 1、如果當前運行的線程數等於corePoolSize,新任務將在無界隊列中等待,因此線程池中的線程數不會超過corePoolSize;
            • 2、maximumPoolSize 與 keepAliveTime 會是無效的;
            • 3、運行中的FixedThreadPool 不會拒絕任務(因爲工作隊列可以無限增大);
        • 2、SingleThreadExecutor,使用單個工作線程的Executor。
          • 創建的方法:
            • 於corePoolSize與maximumPoolSize 設爲1,其它參數與FixedThreadPool一樣。
          • 執行execute(),流程如下:
            • 1、如果線程池中無運行的線程,則創建一個新線程來執行任務;
            • 2、當前線程池中有一個運行的線程,將任務加入LinkedBlockingQueue;
            • 3、線程執行完1中的任務後,會在循環中反覆從LinkedBlockingQueue獲取任務來執行。
          • 使用無界隊列LinkedBlockingQueue,與FixedThreadPool一樣的結果。
        • 3、CachedThreadPool,根據需要創建新線程的線程池。
          • 創建的方法:
            • corePoolSize 爲0,maximumPoolSize被設置爲Integer.MAX_VALUE,即是maximumPoolSize無界的。keepAliveTime 設爲60秒,空閒存活60秒後被終止。
          • CachedThreadPool 使用沒有容量的SynchronousQueue作爲線程池的工作隊列,但是maximumPoolSize是無界的。這意味着,如果主線程提交任務的速度高於maximumPool中線程處理任務的速度時,CachedThreadPool會不斷創建新線程。極端情況下,CachedThreadPool會因爲創建過多線程而耗盡CPU和內存資源。
        • 總結:
          • FixedThreadPool 與 SingleThreadExecutor 允許的請求隊列長度爲Integer.MAX_VALUE,可能會堆積大量的請求,從而引起OOM異常
          • CachedThreadPool => 允許創建的線程數爲Integer.MAX_VALUE,可能會創建大量的線程,從而引起OOM異常
    • FutureTask
      • 使用:
        • 1、由調用線程直接執行FutureTask.run(); ---- 實現了Runnable接口
        • 2、通過ExecutorService.submit()方法返回一個FutureTask; ---- 實現了Future 接口
      • 實現原理
        • 基於AbstractQueuedSynchronizer(簡稱AQS)。AQS是一個同步框架,它提供通用機制來原子性管理同步狀態、阻塞和喚醒線程,以及維護被阻塞線程的隊列。
        • 基於AQS實現的同步器包含兩種類型:
          • 1、至少一個acquire操作。這個操作阻塞調用線程,除非/直到AQS的狀態允許這個線程繼續執行。
            • 在FutureTask 類中get()和get(long timeout, TimeUnit unit)兩個方法爲acquire操作;
          • 2、至少一個release操作。這個操作改變AQS的狀態,改變後的狀態可允許一個或多個阻塞線程被解除阻塞。
            • 在FutureTask 類中run()和cancel()兩個方法爲acquire操作;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章