Java多線程之ExecutorService

 講到Java多線程,大多數人腦海中跳出來的是Thread、Runnable、synchronized……這些是最基本的東西,雖然已經足夠強大,但想要用好還真不容易。從JDK 1.5開始,增加了java.util.concurrent包,它的引入大大簡化了多線程程序的開發(要感謝一下大牛Doug Lee)。 java.util.concurrent包分成了三個部分,分別是java.util.concurrent、java.util.concurrent.atomic和java.util.concurrent.lock。內容涵蓋了併發集合類、線程池機制、同步互斥機制、線程安全的變量更新工具類、鎖等等常用工具。 爲了便於理解,本文使用一個例子來做說明,交代一下它的場景: 假設要對一套10個節點組成的環境進行檢查,這個環境有兩個入口點,通過節點間的依賴關係可以遍歷到整個環境。依賴關係可以構成一張有向圖,可能存在環。爲了提高檢查的效率,考慮使用多線程。

  在稍老一些的Java版本中,具體是在Java 5.0以前,啓動一個任務是通過調用Thread類的start()方法來實現的,任務的提交和執行時同時進行的,如果想對任務的執行進行調度,或者想控制同時執行的線程數量就需要額外編寫代碼來完成。而在Java 5.0裏提供了一個新的任務執行架構使我們可以很輕鬆地調度和控制任務的執行。這個架構主要有三個接口和其相應的類組成。這三個接口分別是:Executor、ExevutirService和ScheduledExecutorService。下面我們來具體說明。

Executor接口:是用來執行Runnable任務的,它值定義了一個方法:

  execute(Runnable command):執行Ruannable類型的任務.

ExecutorService接口:ExecutorService繼承了Executor的方法,並提供了執行Callable任務和中指任務執行的服務,其定義的方法主要有:

  submit(task):可用來提交Callable或Runnable任務,並返回代表此任務的Future對象

  invokeAll(collection of tasks):批處理任務集合,並返回一個代表這些任務的Future對象集合

  shutdown():在完成已提交的任務後關閉服務,不再接受新任務

  shutdownNow():停止所有正在執行的任務並關閉服務。

  isTerminated():測試是否所有任務都執行完畢了。

  isShutdown():測試是否該ExecutorService已被關閉

ScheduledExecutorService接口:

在ExecutorService的基礎上,ScheduledExecutorService提供了按時間安排執行任務的功能,它提供的方法主要有:

  schedule(task, initDelay): 安排所提交的Callable或Runnable任務在initDelay指定的時間後執行

  scheduleAtFixedRate():安排所提交的Runnable任務按指定的間隔重複執行

  scheduleWithFixedDelay():安排所提交的Runnable任務在每次執行完後,等待delay所指定的時間後重復執行

_________________________________________________________________________________________________________________________________

雖然以上提到的接口有其實現類,但是爲了方便,我們建議使用Executors的工具類來得到Executor接口的具體對象,需要注意的是,Executors是一個類,不是Executor的複數形式,Executor提供了一下一些靜態方法:

callable(Runnable task):將一個Runnable的任務轉化成callable的任務

newSingleThreadExecutor: 產生一個ExecutorService對象,這個對象只有一個線程可用來執行任務,若任務多於一個,任務將按先後順序執行

newCachedThreadPool(): 產生一個ExecutorService對象,這個對象帶有一個線程池,線程池的大小會根據需要調整,線程執行完任務後返回線程池,供執行下一次任務使用。

newFixedThreadPool(int poolSize):產生一個ExecutorService對象,這個對象帶有一個大小爲poolSize的線程池,若任務數量大於poolSize,任務會被放在一個queue裏順序執行

newSingleThreadScheduledExecutor:產生一個ScheduledExecutorService對象,這個對象的線程池大小爲1,若任務多於一個,任務將按先後順序執行

newScheduledThreadPool(int poolSize): 產生一個ScheduledExecutorService對象,這個對象的線程池大小爲poolSize,若任務數量大於poolSize,任務會在一個queue裏等待執行

 

1、Executors 通過這個類能夠獲得多種線程池的實例,例如可以調用newSingleThreadExecutor()獲得單線程的ExecutorService,調用newFixedThreadPool()獲得固定大小線程池的ExecutorService。拿到ExecutorService可以做的事情就比較多了,最簡單的是用它來執行Runnable對象,也可以執行一些實現了Callable<t>的對象。用Thread的start()方法沒有返回值,如果該線程執行的方法有返回值那用ExecutorService就再好不過了,可以選擇submit()、invokeAll()或者invokeAny(),根據具體情況選擇合適的方法即可。

2. Atomics原子級變量 原子量級的變量,主要的類有AtomicBoolean, AtomicInteger, AotmicIntegerArray, AtomicLong, AtomicLongArray, AtomicReference ……。這些原子量級的變量主要提供兩個方法: compareAndSet(expectedValue, newValue):比較當前的值是否等於expectedValue,若等於把當前值改成newValue,並返回true。若不等,返回false。 getAndSet(newValue):把當前值改爲newValue,並返回改變前的值。 這些原子級變量利用了現代處理器(CPU)的硬件支持可把兩步操作合爲一步的功能,避免了不必要的鎖定,提高了程序的運行效率。

 

綜合實例

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