前面介紹了線程的幾種運行方式,無論哪一種方式,一旦調用了線程實例的start方法,都會當即啓動線程的事務處理。然而某些業務場景在事務執行時間方面有特殊需求,例如指望延遲若干時間以後纔開始事務運行,又如指望每隔若干時間依次啓動事務處理,如此種種都要求在指定的時間才能啓動線程任務,也就是俗稱的定時功能。
有別於通常的線程,Java爲定時功能設計了專門的定時任務TimerTask,以及定時器Timer。其中TimerTask用來描述時刻到達後的事務處理,而Timer用來調度定時任務,包括什麼時候啓動定時任務、須要間隔多久纔再次運行定時任務等等。
定時任務TimerTask的代碼定義相似Runnable,兩者均需重寫run方法填寫任務代碼,不一樣的是,Runnable任務須要實現Runnable接口,定時任務則由TimerTask類派生而來。下面是個計數用的定時任務代碼例子:html
// 定義一個用於計數的定時任務 private static class CountTask extends TimerTask { private int count = 0; // 計數值 @Override public void run() { // 如下打印計很多天志,包括當前時間、當前線程、計數值等信息 PrintUtils.print(Thread.currentThread().getName(), "當前計數值爲"+count); count++; } }
接下來輪到讓定時器來調度定時任務,定時器Timer的調度方法主要有schedule和scheduleAtFixedRate兩個,不過schedule重載了多個同名方法,依據重載參數的數量區別,可將調度方法劃分爲下列三類用途:ide
一、帶兩個參數的schedule方法,其中第一個參數爲定時任務,第二個參數爲任務的啓動時間或者延遲啓動間隔。這種schedule方法只會啓動唯一一次定時任務。
二、帶三個參數的schedule方法,其中第一個參數爲定時任務,第二個參數爲任務的啓動時間或者延遲啓動間隔,第三個參數爲以後繼續啓動的時間間隔。這種schedule方法會持續不斷地啓動定時任務。
三、scheduleAtFixedRate方法,其中第一個參數爲定時任務,第二個參數爲任務的啓動時間或者延遲啓動間隔,第三個參數爲以後每次啓動的時間間隔。scheduleAtFixedRate方法也會持續不斷地啓動定時任務。
後面兩種調度方式,乍看之下沒什麼區別,都是每隔一段時間啓動後續的任務。其實仍是有點小區別的,帶三個參數的schedule方法,下個任務要在上個任務結束以後再間隔若干時間才啓動;至於scheduleAtFixedRate方法,下個任務無論上個任務什麼時候結束,只要相互之間的啓動間隔到達,便可當即啓動下個任務。因此呢,schedule方式的下次啓動時間與任務執行耗時有關,而scheduleAtFixedRate方式與任務耗時無關,它纔是真正意義上以固定頻率運行着的定時調度。
講完了定時器的幾種調度方式,再來看定時器的具體操做代碼,以schedule方法爲例,經過該方法延遲若干時間後啓動定時任務的代碼以下所示:測試
// 測試只跑一次的定時器調度 private static void testScheduleOnce() { CountTask timerTask = new CountTask(); // 建立一個計數的定時任務 Timer timer = new Timer(); // 建立一個定時器 // 命令定時器啓動定時任務。調度規則爲:延遲50毫秒後啓動。 timer.schedule(timerTask, 50); try { Thread.sleep(1000); // 睡眠1秒 } catch (InterruptedException e) { e.printStackTrace(); } timer.cancel(); // 取消定時器 }
把上面的schedule方法改成固定間隔啓動定時任務的話,只需添加第三個參數就行了,調用代碼片斷示例以下:線程
// 命令定時器啓動定時任務。調度規則爲:延遲50毫秒後啓動,且上一個任務執行完畢間隔100毫秒再執行下一個任務 timer.schedule(timerTask, 50, 100);
或者改爲使用scheduleAtFixedRate方法以固定速度啓動定時任務,此時的調用代碼片斷見下:設計
// 命令定時器啓動定時任務。調度規則爲:延遲50毫秒後啓動,且以後每間隔100毫秒再執行一個任務 timer.scheduleAtFixedRate(timerTask, 50, 100);
運行以上的定時器代碼,觀察到如下的定時日誌,可見定時任務被放到名叫Timer-0的分線程中執行了:日誌
19:01:49.634 Timer-0 當前計數值爲0 19:01:49.661 Timer-0 當前計數值爲1 19:01:49.761 Timer-0 當前計數值爲2 19:01:49.861 Timer-0 當前計數值爲3 ………………………這裏省略餘下的日誌……………………
另外注意一點,定時任務TimerTask和定時器Timer都提供了cancel方法,TimerTask的cancel方法取消的是原來的定時任務,取消以後,還能經過定時器來調度新建立的定時任務。而Timer的cancel方法取消的是定時器自身,一旦取消定時器,那麼不但原來的定時任務被一塊撤銷,並且該定時器不能再調度任何一個定時任務,至關於這個定時器完全報廢了,除非再次建立全新的定時器才能開展調度工做。htm
更多Java技術文章參見《Java開發筆記(序)章節目錄》blog