說到任務調度,你們可能會想到Quartz框架,可是jdk自帶的簡單任務調度工具類,反而瞭解的人並非不少。我以爲若是你的業務相對簡單的話,不必非得用Quartz等框架,使用Timer徹底能夠勝任的。簡單來分享一下我瞭解的Timer。java
Timer是jdk中提供的一個定時器工具,使用的時候會在主線程以外起一個單獨的線程執行指定的計劃任務,能夠指定執行一次或者反覆執行屢次。框架
TimerTask是一個實現了Runnable接口的抽象類,表明一個能夠被Timer執行的任務。ide
我是用TimerTask來建立一個任務,其中run方法裏是任務調度的邏輯。使用一個Timer對象來調度任務。工具
首先給一個特別簡單的示例:測試
package com.tgb.ccl.schema; import java.util.Date; import java.util.TimerTask; /** * 不可動態修改的任務 * * @author arron * @date 2015年5月7日 下午1:52:15 * @version 1.0 */ public class FixedTimerTask extends TimerTask{ @Override public void run() { Date d = new Date(); for(int i=0;i<3;i++){ try { Thread.sleep(1000); System.out.println("已執行【"+(i+1)+"】秒鐘,at: "+d.toLocaleString()); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("本次任務調度結束,at: "+new Date().toLocaleString()); System.out.println("---------------------------"); } }
package com.tgb.ccl.schema; import java.util.Calendar; import java.util.Date; import java.util.Timer; /** * 任務調度管理器 * * @author arron * @date 2015年5月7日 下午1:57:19 * @version 1.0 */ public class TaskManager { // private static final long PERIOD = 5 * 60 * 1000;// 5分鐘 private static final long PERIOD = 5 * 1000;// 1秒鐘 public TaskManager() { Timer timer = new Timer(); FixedTimerTask task = new FixedTimerTask(); System.out.println("start"); //0表示當即執行一次,之後每隔一段時間執行一次 timer.schedule(task, 0, PERIOD); //1000表示1秒後執行一次,之後每隔一段時間執行一次 //timer.schedule(task, 1000, PERIOD); //0表示當即執行一次,之後每隔一段時間執行一次 //timer.schedule(task, 1000, PERIOD); // 在當天14點4分整,執行一次,之後再也不執行 //timer.schedule(task, bookTime(15,0,0)); //在當天14點4分整,執行一次,之後每隔一段時間執行一次 //若是時間超過了設定時間,會當即執行一次 // timer.schedule(task, bookTime(0,34,10),PERIOD); // timer.scheduleAtFixedRate(task, bookTime(0,40,0),PERIOD); } private Date bookTime(int hour, int minute, int second) { Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY, hour); calendar.set(Calendar.MINUTE, minute); calendar.set(Calendar.SECOND, second); Date date = calendar.getTime(); return date; } public static void main(String[] args) { new TaskManager(); } }
只要執行main方法就能夠測試了。
spa
你們可能已經注意到了,timer的schedule方法是重載的。參數主要有必須有一個TimerTask實例。第二個參數若是是long類型的,這個參數則是表示延遲時間,以毫秒爲單位。若是爲1000,那就是1秒後執行任務調度。若是是Date類型,則表示設定任務開始執行的時刻。當時間到達這個時刻,那麼任務會自動開始調度。固然若是當前時間已經超過了設定的開始時間,那麼會當即執行一次。第三個參數則是可選參數,是long類型的參數,表示調度的間隔時間。若是有這個參數,表示任務是重複性的調度。不然只會執行一次。這個參數依舊以毫秒爲單位。線程
若是你稍微注意一下,就會發現timer不僅提供了schedule方法,還提供了scheduleAtFixedRate方法。這兩個方法都是任務調度方法,他們有什麼區別呢?code
區別在於噹噹前時間已經超過了設定執行時間,schedule方法會當即執行,第二次執行則是按當前執行時間+間隔時間來算的(固然任務執行時間超過了間隔時間,則在第一次執行完畢後,立馬會執行第二次)。而scheduleAtFixedRate方法,一樣是當即執行一次,可是它第二次執行則是按照(當前執行時間-設定的時間)/時間間隔來計算從設定時間到如今還須要執行多少次。對象
舉個例子:任務調度須要執行2s,間隔時間是10s,我設定的是8點執行。當前時間爲8點0分10秒,若是是schedule方法,則會當即執行一次,第二次執行時間則是08:00:20。若是是scheduleAtFixedRate方法,則會當即執行一次,而後計算08:00:10-08:00:00整好還能夠執行一次,因此會在08:00:12時,會當即再執行一次,第三次執行則是在08:00:20時執行,之後每隔10s執行一次。接口
(左圖是schedule方法的測試效果,右圖是scheduleAtFixedRate方法的測試效果)
這個跟網上不少人說的不太同樣。不過這個是我測試出來了。他們說的那種結果反正我是測不出來。具體你相信哪一種,你本身試過就清楚了。
下篇分享一下怎樣動態修改Timer的調度計劃,敬請期待。