1.用timer缺點很是大
java
Timer 的優勢在於簡單易用,但因爲全部任務都是由同一個線程來調度,所以全部任務都是串行執行的,同一時間只能有一個任務在執行,前一個任務的延遲或異常都將會影響到以後的任務。多線程
咱們關於定時/週期操做都是經過Timer來實現的。可是Timer有如下幾種危險
a. Timer是基於絕對時間的。容易受系統時鐘的影響。
b. Timer只新建了一個線程來執行全部的TimeTask。全部TimeTask可能會相關影響
c. Timer不會捕獲TimerTask的異常,只是簡單地中止。這樣勢必會影響其餘TimeTask的執行。 併發
2.ScheduledThreadPoolExecutor.net
鑑於 Timer 的上述缺陷,Java 5 推出了基於線程池設計的ScheduledThreadPoolExecutor。其設計思想是,每個被調度的任務都會由線程池中一個線程去執行,所以任務是併發執行的,相互之間不會受到干擾。需 要注意的是,只有當任務的執行時間到來時,ScheduedExecutor 纔會真正啓動一個線程,其他時間 ScheduledExecutor 都是在輪詢任務的狀態。線程
有如下四個調度器的方法:設計
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit); public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit); public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit); public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);
那麼這四個方法有什麼區別呢?其實第一個和第二個區別不大,一個是Runnable、一個是Callable,內部包裝後是同樣的效果;因此把頭兩個方法幾乎當成一種調度,那麼三種狀況分別是:code
一、 進行一次延遲調度:延遲delay這麼長時間,單位爲:TimeUnit傳入的的一個基本單位,例如:TimeUnit.SECONDS屬於提供好的枚舉信息;(適合於方法1和方法2)。排序
二、 屢次調度,每次依照上一次預計調度時間進行調度,例如:延遲2s開始,5s一次,那麼就是二、七、十二、17,若是中間因爲某種緣由致使線程不夠用,沒有獲得調度機會,那麼接下來計算的時間會優先計算進去,由於他的排序會被排在前面,有點相似Timer中的:scheduleAtFixedRate方法,只是這裏是多線程的,它的方法名也叫:scheduleAtFixedRate,因此這個是比較好記憶的(適合方法3)get
三、 屢次調度,每次按照上一次實際執行的時間進行計算下一次時間,同上,若是在第7秒沒有被獲得調度,而是第9s才獲得調度,那麼計算下一次調度時間就不是12秒,而是9+5=14s,若是再次延遲,就會延遲一個週期以上,也就會出現少調用的狀況(適合於方法3);it
四、 最後補充execute方法是一次調度,指望被當即調度,時間爲空
public class ScheduledThreadPoolExecutorDemo { public static void main(String[] args) { ScheduledThreadPoolExecutor scheduledExecutor = new ScheduledThreadPoolExecutor(1); /** * new timeTaskForException() 要執行的任務線程 * 1000:延遲多長時間執行 * 2000: 每隔多少長時間執行一次 * TimeUnit.MILLISECONDS:時間單位 */ scheduledExecutor.scheduleAtFixedRate(new timeTaskForException(), 1000, 2000, TimeUnit.MILLISECONDS); scheduledExecutor.scheduleAtFixedRate(new timeTaskForPrintSYSTime(), 1000, 3000, TimeUnit.MILLISECONDS); } static class timeTaskForException implements Runnable{ public void run() { throw new RuntimeException(); } } static class timeTaskForPrintSYSTime implements Runnable { public void run() { System.out.println(System.nanoTime()); } } }