深刻淺出 Java Concurrency (29): 線程池 part 2 Executor 以及Executors[轉]

Java裏面線程池的頂級接口是Executor,可是嚴格意義上講Executor並非一個線程池,而只是一個執行線程的工具。真正的線程池接口是ExecutorService。java

下面這張圖完整描述了線程池的類體系結構。緩存

Executor-class

首先Executor的execute方法只是執行一個Runnable的任務,固然了從某種角度上將最後的實現類也是在線程中啓動此任務的。根據線程池的執行策略最後這個任務可能在新的線程中執行,或者線程池中的某個線程,甚至是調用者線程中執行(至關於直接運行Runnable的run方法)。這點在後面會詳細說明。併發

ExecutorService在Executor的基礎上增長了一些方法,其中有兩個核心的方法:高併發

  • Future<?> submit(Runnable task)
  • <T> Future<T> submit(Callable<T> task)

這兩個方法都是向線程池中提交任務,它們的區別在於Runnable在執行完畢後沒有結果,Callable執行完畢後有一個結果。這在多個線程中傳遞狀態和結果是很是有用的。另外他們的相同點在於都返回一個Future對象。Future對象能夠阻塞線程直到運行完畢(獲取結果,若是有的話),也能夠取消任務執行,固然也可以檢測任務是否被取消或者是否執行完畢。工具

在沒有Future以前咱們檢測一個線程是否執行完畢一般使用Thread.join()或者用一個死循環加狀態位來描述線程執行完畢。如今有了更好的方法可以阻塞線程,檢測任務執行完畢甚至取消執行中或者未開始執行的任務。操作系統

 

ScheduledExecutorService描述的功能和Timer/TimerTask相似,解決那些須要任務重複執行的問題。這包括延遲時間一次性執行、延遲時間週期性執行以及固定延遲時間週期性執行等。固然了繼承ExecutorService的ScheduledExecutorService擁有ExecutorService的所有特性。.net

 

ThreadPoolExecutor是ExecutorService的默認實現,其中的配置、策略也是比較複雜的,在後面的章節中會有詳細的分析。線程

ScheduledThreadPoolExecutor是繼承ThreadPoolExecutor的ScheduledExecutorService接口實現,週期性任務調度的類實現,在後面的章節中會有詳細的分析。對象

這裏須要稍微提一下的是CompletionService接口,它是用於描述順序獲取執行結果的一個線程池包裝器。它依賴一個具體的線程池調度,可是可以根據任務的執行前後順序獲得執行結果,這在某些狀況下可能提升併發效率。blog

 

要配置一個線程池是比較複雜的,尤爲是對於線程池的原理不是很清楚的狀況下,頗有可能配置的線程池不是較優的,所以在Executors類裏面提供了一些靜態工廠,生成一些經常使用的線程池。

  • newSingleThreadExecutor:建立一個單線程的線程池。這個線程池只有一個線程在工做,也就是至關於單線程串行執行全部任務。若是這個惟一的線程由於異常結束,那麼會有一個新的線程來替代它。此線程池保證全部任務的執行順序按照任務的提交順序執行。
  • newFixedThreadPool:建立固定大小的線程池。每次提交一個任務就建立一個線程,直到線程達到線程池的最大大小。線程池的大小一旦達到最大值就會保持不變,若是某個線程由於執行異常而結束,那麼線程池會補充一個新線程。
  • newCachedThreadPool:建立一個可緩存的線程池。若是線程池的大小超過了處理任務所須要的線程,那麼就會回收部分空閒(60秒不執行任務)的線程,當任務數增長時,此線程池又能夠智能的添加新線程來處理任務。此線程池不會對線程池大小作限制,線程池大小徹底依賴於操做系統(或者說JVM)可以建立的最大線程大小。
  • newScheduledThreadPool:建立一個大小無限的線程池。此線程池支持定時以及週期性執行任務的需求。
  • newSingleThreadScheduledExecutor:建立一個單線程的線程池。此線程池支持定時以及週期性執行任務的需求。

在詳細講解ThreadPoolExecutor的時候會具體討論上述參數配置後的意義和原理。

線程池是一個複雜的任務調度工具,所以它涉及到任務、線程池等的生命週期問題,在下一節中來探討下這個問題。

相關文章
相關標籤/搜索