在Timer和 ScheduledExecutorService間決擇

http://dev.firnow.com/course/3_program/java/javajs/20100719/461320.html

java.util.Timer計時器有管理任務延遲執行("如1000ms後執行任務")以及週期性執行("如每500ms執行一次該任務")。但是,Timer存在一些缺陷,因此你應該考慮使用 ScheduledThreadPoolExecutor作爲代替品,Timer對調度的支持是基於絕對時間,而不是相對時間的,由此任務對系統時鐘的改變是敏感的;ScheduledThreadExecutor只支持相對時間。

    Timer的另一個問題在於,如果TimerTask拋出未檢查的異常,Timer將會產生無法預料的行爲。Timer線程並不捕獲異常,所以 TimerTask拋出的未檢查的異常會終止timer線程。這種情況下,Timer也不會再重新恢復線程的執行了;它錯誤的認爲整個Timer都被取消了。此時,已經被安排但尚未執行的TimerTask永遠不會再執行了,新的任務也不能被調度了。

 測試Timer的例子

package com.bill99.test;

import java.util.Timer;
import java.util.TimerTask;

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了。

 用ScheduledThreadPoolExector改進後的例子:

package com.bill99.test;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledExecutorTest {
//線程池能按時間計劃來執行任務,允許用戶設定計劃執行任務的時間,int類型的參數是設定
//線程池中線程的最小數目。當任務較多時,線程池可能會自動創建更多的工作線程來執行任務
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();
}
}
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章