在Java 5.0之前啓動一個任務是通過調用Thread類的start()方法來實現的,任務的提於交和執行是同時進行的,如果你想對任務的執行進行調度或是控制 同時執行的線程數量就需要額外編寫代碼來完成。5.0裏提供了一個新的任務執行架構使你可以輕鬆地調度和控制任務的執行,並且可以建立一個類似數據庫連接 池的線程池來執行任務。這個架構主要有三個接口和其相應的具體類組成。這三個接口是Executor, ExecutorService、ScheduledExecutorService,讓我們先用一個圖來顯示它們的關係:
圖的左側是接口,圖的右側是這些接口的具體類。注意Executor是沒有直接具體實現的。
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 類
雖然以上提到的接口有其實現的具體類,但爲了方便Java 5.0建議使用Executors的工具類來得到Executor接口的具體對象,需要注意的是Executors是一個類,不是Executor的複數 形式。Executors提供了以下一些static的方法:
- callable(Runnable task): 將Runnable的任務轉化成Callable的任務
- newSingleThreadExecutor:創建一個單線程的線程池。這個線程池只有一個線程在工作,也就是相當於單線程串行執行所有任務。如果這個唯一的線程因爲異常結束,那麼會有一個新的線程來替代它。此線程池保證所有任務的執行順序按照任務的提交順序執行。
- newFixedThreadPool:創建固定大小的線程池。每次提交一個任務就創建一個線程,直到線程達到線程池的最大大小。線程池的大小一旦達到最大值就會保持不變,如果某個線程因爲執行異常而結束,那麼線程池會補充一個新線程。
- newCachedThreadPool:創建一個可緩存的線程池。如果線程池的大小超過了處理任務所需要的線程,那麼就會回收部分空閒(60秒不執行任務)的線程,當任務數增加時,此線程池又可以智能的添加新線程來處理任務。此線程池不會對線程池大小做限制,線程池大小完全依賴於操作系統(或者說JVM)能夠創建的最大線程大小。
- newScheduledThreadPool:創建一個大小無限的線程池。此線程池支持定時以及週期性執行任務的需求。
- newSingleThreadExecutor:創建一個單線程的線程池。此線程池支持定時以及週期性執行任務的需求。