在要定時(shí)執(zhí)行某一任務(wù)時(shí),在精度不是要求很高的情況下,一般使用Java.util.TimerTask類來完成(要精確度較高的要求下可采用Quarta開源插件),使用
TimerTask類完成定時(shí)任務(wù)開發(fā)時(shí),很簡(jiǎn)單,只需以下二步:
!)定義一個(gè)繼承TimerTask類的類,重寫run()方法,在該方法中實(shí)現(xiàn)自已的業(yè)務(wù)邏輯;
2)在主類中定義一個(gè)Timer類對(duì)象,用該對(duì)象的schedule()或scheduleAtFixedRate()來實(shí)現(xiàn)定時(shí)任務(wù)的執(zhí)行(這兩個(gè)方法有一定的區(qū)別,這里不作介紹);
這樣就完成了任務(wù)的定時(shí)執(zhí)行,其實(shí) TimerTask類也是基于線程(Thread)的實(shí)現(xiàn),所以繼承了TimerTask的類要重寫run()方法,在該方法中實(shí)現(xiàn)自已的任務(wù).
現(xiàn)在有一點(diǎn)要說明下,即在創(chuàng)建Timer類對(duì)象時(shí),有兩種方法:
1)Timer tm = new Timer(); //創(chuàng)建一個(gè)非守護(hù)線程
2)Timer tm = new Timer(true); //創(chuàng)建一守護(hù)線程
讓timer線程成為一個(gè)daemon線程,這樣當(dāng)程序只有daemon線程的時(shí)候,它就會(huì)自動(dòng)終止運(yùn)行.如果有非守護(hù)線程在運(yùn)行,則守護(hù)線程一直存在.
現(xiàn)舉例如下:
1)




TestTask()類中重寫的run()方法很簡(jiǎn)單,只是輸出一條語句,但這段代碼是沒有輸出結(jié)果的,因?yàn)橹骶€程啟動(dòng)后就停止了,所以tm這個(gè)守護(hù)線程就也不存在了,所以沒有輸出結(jié)果,現(xiàn)在改下代碼:
2)











但這段代碼也還是沒有輸出的,因?yàn)橹骶€程睡眠了6秒鐘后,守護(hù)線程才產(chǎn)生,但這時(shí)主線程睡眠了6秒鐘后就已經(jīng)消亡了,所以守護(hù)線程就也不存在了,但如果讓主線程睡眠放在schedule()方法后面執(zhí)行,則就會(huì)有輸出,即:
3)










另:這里有幾種情況要說明下:
1)上面幾種例舉的情況是指創(chuàng)建守護(hù)線程(即創(chuàng)建Timer對(duì)象時(shí)帶true這個(gè)參數(shù),如果不帶參數(shù),則表示創(chuàng)建的是非守護(hù)線程)的情況,如果創(chuàng)建的是非守護(hù)線程,則不管哪種情況,一定會(huì)有輸出的.
2)針對(duì)上面幾種情況,如果在調(diào)用schedule()方法時(shí),使用的是三個(gè)參數(shù)的(上面都是帶兩個(gè)參數(shù)),且第二個(gè)參數(shù)為0的話,則上面的幾種情況,也都是會(huì)有輸出的,因?yàn)榈诙€(gè)參數(shù)為0的話,表示的意思是立即執(zhí)行.如上面第二種情況,如果改成這樣:tm.schedule(new TestTask(),0,2*1000);守護(hù)線程雖然后是等主線程睡眠6秒主才產(chǎn)生(且這時(shí)主線程已經(jīng)消亡),但產(chǎn)生守護(hù)線程時(shí),守護(hù)線程立即執(zhí)行,所以也會(huì)能輸出.
注:守護(hù)線程的特點(diǎn)是,只要線程隊(duì)列中沒有非守護(hù)線程(即普通的我們常見的線程都為非守護(hù)線程),則所有的守護(hù)線程也將全部消亡.
創(chuàng)建守護(hù)線程的方法是,線程對(duì)象調(diào)用: threadObj.setDaemon(true);即可將threadObj該線程設(shè)為守護(hù)線程.