轉載請註明出處:http://blog.csdn.net/l1028386804/article/details/48050505
java.util.Timer計時器有管理工作順延強制("如1000ms後執行任務")以及周期性執行("如每500ms執行一次該任務")。 但是,Timer存在一些缺陷,因此你應該考慮使用ScheduledThreadPoolExecutor作為代替品,Timer對調度的支援是基於絕對時間,而不是相對時間的,
由此任務對系統時鐘的改變是敏感的;ScheduledThreadExecutor只支援相對時間。
Timer的另一個問題在於,如果TimerTask拋出未檢查的異常,Timer將會產生無法預料的行為。
Timer線程並不捕獲異常,所以TimerTask拋出的未檢查的異常會終止timer線程。
這種情況下,Timer也不會再重新恢複線程的執行了;它錯誤的認為整個Timer都被取消了。
此時,已經被安排但尚未執行的TimerTask永遠不會再執行了,新的任務也不能被調度了。
個人總結:timer的bug:60秒執行一次的話,如果使用者修改了時間的話 那麼時針都會歸0,本來是臨近10秒執行的時候timer又會重新計時一次 再等60才執行。
測試Timer例子:
package com.lyz.test; import java.util.Timer; import java.util.TimerTask; /** * 測試Timer樣本程式 * @author liuyazhuang */ public class TimerTest { private Timer timer = new Timer(); //啟動計時器 public void lanuchTimer(){ timer.schedule(new TimerTask(){ public void run() { throw new RuntimeException(); } }, 1000*3, 500); } //向計時器添加一個任務 public void addOneTask(){ timer.schedule(new TimerTask(){ public void run(){ System.out.println("hello world"); } }, 1000*1,1000*5); } public static void main(String[] args) throws Exception { TimerTest test = new TimerTest(); test.lanuchTimer(); Thread.sleep(1000*5);//5秒鐘之後添加一個新任務 test.addOneTask(); } }運行該程式,Timer會拋出一個RumtimeException和java.lang.IllegalStateException:Timer already cancelled.
常言道,真是禍不單行,Timer還將它的問題傳染給下一個倒黴的調用者,這個調用者原本試圖提交一個TimerTask的,你可能希望程式會一直運行下去,然而實際情況如程式所示5秒鐘後就中止了,還伴隨著一個異常,異常的訊息是"Timer already cancelled"。ScheduledThreadPoolExector妥善地處理了這個異常的任務,所以說在java5.0或更高的JDK中,幾乎沒有理由再使用Timer了。
Timer的測試結果所圖所示
用ScheduledThreadPoolExector改進後的例子
package com.lyz.test; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** * ScheduledThreadPoolExector測試程式 * @author liuyazhuang * */public class ScheduledExecutorTest { //線程池能按時間計劃來執行任務,允許使用者設定計劃執行任務的時間,int類型的參數是設定 //線程池中線程的最小數目。當任務較多時,線程池可能會自動建立更多的背景工作執行緒來執行任務 //此處用Executors.newSingleThreadScheduledExecutor()更佳。 public ScheduledExecutorService scheduExec = Executors.newScheduledThreadPool(1); //啟動計時器 public void lanuchTimer(){ Runnable task = new Runnable() { public void run() { throw new RuntimeException(); } }; scheduExec.scheduleWithFixedDelay(task, 1000*5, 1000*10, TimeUnit.MILLISECONDS); } //添加新任務 public void addOneTask(){ Runnable task = new Runnable() { public void run() { System.out.println("welcome to china"); } }; scheduExec.scheduleWithFixedDelay(task, 1000*1, 1000, TimeUnit.MILLISECONDS); } public static void main(String[] args) throws Exception { ScheduledExecutorTest test = new ScheduledExecutorTest(); test.lanuchTimer(); Thread.sleep(1000*5);//5秒鐘之後添加新任務 test.addOneTask(); } }從下面的運行截圖可以看出,即使計時器內部發生了異常也不影響正常的調用,你不必擔心ScheduleExecutor會發生異常而導致計時器停止,而Timer則會因為異常而停止。