本文轉(zhuǎn)載自 http://blog.csdn.net/nalw2012/article/details/49633413
java.util.Timer計(jì)時(shí)器有管理任務(wù)延遲執(zhí)行("如1000ms后執(zhí)行任務(wù)")以及周期性執(zhí)行("如每500ms執(zhí)行一次該任務(wù)")癞蚕。但是,Timer存在一些缺陷辉哥,因此你應(yīng)該考慮使用ScheduledThreadPoolExecutor作為代替品.
Timer對調(diào)度的支持是基于絕對時(shí)間,而不是相對時(shí)間的桦山,由此任務(wù)對系統(tǒng)時(shí)鐘的改變是敏感的;ScheduledThreadExecutor只支持相對時(shí)間。
Timer的另一個(gè)問題在于,如果TimerTask拋出未檢查的異常度苔,Timer將會產(chǎn)生無法預(yù)料的行為匆篓。Timer線程并不捕獲異常浑度,所以TimerTask拋出的未檢查的異常會終止timer線程寇窑。這種情況下,Timer也不會再重新恢復(fù)線程的執(zhí)行了;它錯(cuò)誤的認(rèn)為整個(gè)Timer都被取消了箩张。此時(shí)甩骏,已經(jīng)被安排但尚未執(zhí)行的TimerTask永遠(yuǎn)不會再執(zhí)行了,新的任務(wù)也不能被調(diào)度了先慷。
個(gè)人總結(jié):timer的bug:60秒執(zhí)行一次的話饮笛,如果用戶修改了時(shí)間的話 那么時(shí)針都會歸0,本來是臨近10秒執(zhí)行的時(shí)候timer又會重新計(jì)時(shí)一次 再等60才執(zhí)行论熙。
測試Timer的例子
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
private Timer timer = new Timer();
//啟動計(jì)時(shí)器
public void lanuchTimer(){
timer.schedule(new TimerTask(){
public void run() {
throw new RuntimeException();
}
}, 1000*3, 500);
}
//向計(jì)時(shí)器添加一個(gè)任務(wù)
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秒鐘之后添加一個(gè)新任務(wù)
test.addOneTask();
}
}
運(yùn)行該程序福青,Timer會拋出一個(gè)RumtimeException和java.lang.IllegalStateException:Timer already cancelled。常言道脓诡,真是禍不單行无午,Timer還將它的問題傳染給下一個(gè)倒霉的調(diào)用者,這個(gè)調(diào)用者原本試圖提交一個(gè)TimerTask的祝谚,你可能希望程序會一直運(yùn)行下去宪迟,然而實(shí)際情況如程序所示5秒鐘后就中止了,還伴隨著一個(gè)異常交惯,異常的消息是"Timer already cancelled"次泽。
ScheduledThreadPoolExector妥善地處理了這個(gè)異常的任務(wù),所以說在java5.0或更高的JDK中席爽,幾乎沒有理由再使用Timer了意荤。
用ScheduledThreadPoolExector改進(jìn)后的例子
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledExecutorTest {
//線程池能按時(shí)間計(jì)劃來執(zhí)行任務(wù),允許用戶設(shè)定計(jì)劃執(zhí)行任務(wù)的時(shí)間只锻,int類型的參數(shù)是設(shè)定
//線程池中線程的最小數(shù)目玖像。當(dāng)任務(wù)較多時(shí),線程池可能會自動創(chuàng)建更多的工作線程來執(zhí)行任務(wù)
//此處用Executors.newSingleThreadScheduledExecutor()更佳炬藤。
public ScheduledExecutorService scheduExec = Executors.newScheduledThreadPool(1);
//啟動計(jì)時(shí)器
public void lanuchTimer(){
Runnable task = new Runnable() {
public void run() {
throw new RuntimeException();
}
};
scheduExec.scheduleWithFixedDelay(task, 1000*5, 1000*10, TimeUnit.MILLISECONDS);
}
//添加新任務(wù)
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秒鐘之后添加新任務(wù)
test.addOneTask();
}