timer定时器_拾遗Timer定时器
一 Timer ?介紹
在開發(fā)中我們經(jīng)常會(huì)遇到一些簡(jiǎn)單定時(shí)任務(wù)的需求,而不需要量級(jí)較重的定時(shí)任務(wù)就可以采取java定時(shí)器;
java.util.Timer工具類中的Timer 是定時(shí)器,但定時(shí)任務(wù)寫在java.util.TimerTask 中,由 Timer 執(zhí)行 TimerTask ;
Timer 的本質(zhì)就是線程,構(gòu)造方法如下
public?Timer(String?name)?{????????thread.setName(name);
????????thread.start();
????}
從源碼角度可知,如果這樣創(chuàng)建定時(shí)器非守護(hù)線程,即使主線程運(yùn)行結(jié)束,定時(shí)任務(wù)還是會(huì)執(zhí)行;如果我們會(huì)使用如下的構(gòu)造方式創(chuàng)建定時(shí)任務(wù)就是守護(hù)線程方式,會(huì)隨著主線程的消亡而消亡;
public?Timer(String?name,?boolean?isDaemon)?{????????thread.setName(name);
????????thread.setDaemon(isDaemon);
????????thread.start();
????}
Timer內(nèi)部維護(hù)了一個(gè)優(yōu)先隊(duì)列,用于順序執(zhí)行TimerTask任務(wù);
private?final?TaskQueue?queue?=?new?TaskQueue();private?final?TimerThread?thread?=?new?TimerThread(queue);
優(yōu)先隊(duì)列的實(shí)現(xiàn)就是數(shù)組方式作為平衡二叉堆
private?TimerTask[]?queue?=?new?TimerTask[128];TimerTask 實(shí)現(xiàn)了Runnable 接口,執(zhí)行的任務(wù)動(dòng)作就是run方法;
public?abstract?class?TimerTask?implements?Runnable?{?//?....
?????protected?TimerTask()?{
????}
????public?abstract?void?run();
?//....
}
所以「定時(shí)器的本質(zhì)就是啟動(dòng)了一個(gè)新的線程執(zhí)行任務(wù),這些任務(wù)都會(huì)維護(hù)在優(yōu)先隊(duì)列里面」;
timer的調(diào)度主要方法如下
- schedule(TimerTask task, long delay) ? 延遲 delay 毫秒執(zhí)行一次
- schedule(TimerTask task, Date time) 指定時(shí)間執(zhí)行一次
- schedule(TimerTask task, long delay, long period) 延遲delay毫秒以后,每隔period毫秒執(zhí)行一次
- schedule(TimerTask task, Date firstTime, long period) 從firstTime時(shí)刻開始,每隔period毫秒執(zhí)行一次
二 Timer使用示例
如果方式簡(jiǎn)單使用Timer去延遲執(zhí)行線程任務(wù),當(dāng)然其它四種方法同理,調(diào)用方式區(qū)別不大;
????public?static?void?main(String[]?args)?{????????//?創(chuàng)建定時(shí)器
????????Timer?timer?=?new?Timer("知識(shí)追尋者");
????????//?創(chuàng)建定時(shí)器任務(wù);實(shí)現(xiàn)run 方法
????????TimerTask?timerTask?=?new?TimerTask()?{
????????????@Override
????????????public?void?run()?{
????????????????System.out.println("線程執(zhí)行了"+?LocalTime.now());
????????????}
????????};
????????System.out.println("程序執(zhí)行時(shí)間"+?LocalTime.now());
????????//?啟動(dòng)定時(shí)器
????????timer.schedule(timerTask,5000);
????}
輸出的間隔大約就是5秒
程序執(zhí)行時(shí)間?18:47:28.258線程執(zhí)行了18:47:33.259
三 cancel 方法
TimerTask的cancel () 方法是將自身任務(wù)從任務(wù)隊(duì)列中移除
我們先延遲2秒,再每2秒執(zhí)行一次看效果
????public?static?void?main(String[]?args)?{????????//?創(chuàng)建定時(shí)器
????????Timer?timer?=?new?Timer("知識(shí)追尋者");
????????//?創(chuàng)建定時(shí)器任務(wù);實(shí)現(xiàn)run 方法
????????TimerTask?timerTask?=?new?TimerTask()?{
????????????@Override
????????????public?void?run()?{
????????????????System.out.println("線程執(zhí)行了"+?LocalTime.now());
????????????}
????????};
????????System.out.println("程序執(zhí)行時(shí)間"+?LocalTime.now());
????????//?啟動(dòng)定時(shí)器
????????timer.schedule(timerTask,2000,2000);
????}
結(jié)果是每2秒會(huì)執(zhí)行一次
程序執(zhí)行時(shí)間18:59:23.557線程執(zhí)行了18:59:25.558
線程執(zhí)行了18:59:27.558
線程執(zhí)行了18:59:29.559
啟用cancel方法,后 就只會(huì)執(zhí)行一次
????public?static?void?main(String[]?args)?{????????//?創(chuàng)建定時(shí)器
????????Timer?timer?=?new?Timer("知識(shí)追尋者");
????????//?創(chuàng)建定時(shí)器任務(wù);實(shí)現(xiàn)run 方法
????????TimerTask?timerTask?=?new?TimerTask()?{
????????????@Override
????????????public?void?run()?{
????????????????System.out.println("線程執(zhí)行了"+?LocalTime.now());
????????????????//?調(diào)用?cancel方法
????????????????this.cancel();
????????????}
????????};
????????System.out.println("程序執(zhí)行時(shí)間"+?LocalTime.now());
????????//?啟動(dòng)定時(shí)器
????????timer.schedule(timerTask,2000,2000);
????}
輸出如下
程序執(zhí)行時(shí)間19:02:12.770線程執(zhí)行了19:02:14.772
Timer的cancel方法是移除所有的任務(wù);
????public?static?void?main(String[]?args)?{????????//?創(chuàng)建定時(shí)器
????????Timer?timer?=?new?Timer("知識(shí)追尋者");
????????//?創(chuàng)建定時(shí)器任務(wù);實(shí)現(xiàn)run 方法
????????TimerTask?timerTask?=?new?TimerTask()?{
????????????@Override
????????????public?void?run()?{
????????????????System.out.println("線程執(zhí)行了"+?LocalTime.now());
????????????}
????????};
????????System.out.println("程序執(zhí)行時(shí)間"+?LocalTime.now());
????????timer.cancel();
????????//?啟動(dòng)定時(shí)器
????????timer.schedule(timerTask,2000,2000);
????}
輸出直接報(bào)錯(cuò)
程序執(zhí)行時(shí)間:19:34.294Exception?in?thread?"main"?java.lang.IllegalStateException:?Timer?already?cancelled.
?at?java.util.Timer.sched(Timer.java:397)
?at?java.util.Timer.schedule(Timer.java:248)
?at?com.youku1327.base.timer.TimerAbsolute.main(TimerAbsolute.java:28)
四 scheduleAtFixedRate
schedule 與 scheduleAtFixedRate ?方法的區(qū)別如下:
schedule 方法如果執(zhí)行任務(wù)的時(shí)間沒有被延遲,下一次執(zhí)行任務(wù)時(shí)間參考的是上一次任務(wù)執(zhí)行的開始時(shí)間
scheduleAtFixedRate ?方法如果執(zhí)行任務(wù)的時(shí)間沒有被延遲,下一次執(zhí)行任務(wù)時(shí)間參考的是上一次任務(wù)執(zhí)行的結(jié)束時(shí)間
五 Timer缺點(diǎn)
- Timer 對(duì)調(diào)度的支持是基于絕對(duì)時(shí)間的,而不是相對(duì)時(shí)間,所以它對(duì)系統(tǒng)時(shí)間的改變非常敏感。
- Timer 線程是不會(huì)捕獲異常的,如果 TimerTask 拋出的了未檢查異常則會(huì)導(dǎo)致 Timer 線程終止。
總結(jié)
以上是生活随笔為你收集整理的timer定时器_拾遗Timer定时器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python操作hdfs_python
- 下一篇: python语句first、*middl