Java線程池深入分析(2)

Executor.java
該接口主要定義將任務提交到線程池的接口方法,爲什麼在該接口中只定義任務的提交方法,在jdk文檔中也給了一個大致的說明(該接口只負責任務提交到線程池,與具體線程池如何執行提交的任務解耦)

ExecutorService
該類主要定義了線程池的關閉方式,以及在Executor的基礎之上封裝了更多類型的任務提交方式,主要有兩種方式:一種是單個任務提交執行;一種是批量任務的提交執行,如:

  1. 單個任務提交方式
    submit(Runnable task):這種方式返回一個future,調用者可以通過該future控制提交任務的執行過程,並且可以通過該返回實例,同步的等待任務的執行結果。
    submit(Runnable task, T result):這種方式是,當任務成功的執行完成的時候,future.get()返回的是result
    多任務提交方式
  2. 列表內容
    invokeAll(Collection<Runnable> tasks...):該接口會等待tasks所有任務完成之後才返回。
    invokeAny(Collection<Runnable> tasks...):該接口是,在提交的tasks所有任務中,只要有一個任務完成,這個接口就返回。

ThreadPoolExecutor
該線程池類是使用較多的線程池類,該線程池有兩種任務處理的方式:
1、當新的任務被添加到該線程池中的時候,線程池中的線程如果達到了配置的數量之後,且沒有空閒的線程的時候,新的任務將被加入到任務隊列中。
2、當新的任務到達之後,線程池中如果沒有空閒的線程,那麼線程池會創建新的線程來執行任務。

在創建該線程池的時候需要傳入較多的參數,主要包含如下幾個參數:
int corePoolSize:線程池中的核心線程數量。當新任務到達的時候,如果線程池中的可用的線程數量小於 corePoolSize的時候,會創建新的線程來執行任務;如果線程池中的可用的線程數量大於等於>= corePoolSize的時候,如果workQueue仍然可以插入任務的時候,線程池不會創建新的線程,如果workQueue不能插入任務了,且當前線程數量小於< maximumPoolSize的時候,線程池會創建新的線程池來處理任務,否則就會拋出RejectedExecutionException。
int maximumPoolSize:當前線程池中允許的最大的線程數量,如果workQueue不能加入新的任務,而且當前線程池中的線程數量等於=maximumPoolSize的時候,會拋出RejectedExecutionException。
long keepAliveTime:當線程池中的線程數量大於corePoolSize,且部分線程空閒的時候,當空閒的線程空閒時間超過該值得時候,空閒的線程將會被銷燬。
TimeUnit unit:標誌keepAliveTime的單位,SECONDE、MINITES…,最終該時間會被轉換爲納秒
BlockingQueue<Runnable> workQueue:用於緩存任務的任務隊列。
ThreadFactory threadFactory:線程池工廠,可以通過自定義線程池工廠,提前創建部分線程,從而達到prestartAllCoreThreads的功能(因爲該功能在線程池中必須保證workQueue中有corePoolSize這麼多的任務)
RejectedExecutionHandler handler:當任務不能被接受的時候的回掉函數。

Executors.java
該類是線程池的工廠類,主要負責線程池的創建,主要通過調用線程池的具體的實現類進行線程池的創建。

使用注意
1、如果你的任務與任務之間有相互的依賴關係,或者是存在鎖的競爭關係的時候,建議使用Executors.newCachedThreadPool();,因爲該線程池會對每個任務創建一個線程,不會導致由於任務不能被執行而引起的死鎖。
2、如果你的任務是獨立的任務,即任務之間沒有依賴關係,那麼可以使用Executors.newFixedThreadPool(int nThreads),這樣效率更高,因爲固定的線程數量使得線程調度的頻率低,線程切換開銷小。

jdk中其他類型的線程池的實現,如批量任務線程池,延遲任務線程池等,將在下一節中進行深入的剖析,當然這些線程池也是可以基於上述的ThreadPoolExecutor實現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章