有時候,我們希望程序在將來的某一時刻執行,也有想過讓它可以重復執行多次!
於是,我們就需要實現定時調度功能。
在java里,由兩個類來共同實現定時調度:java.util.Timer 和 java.util.TimerTask
Timer可以理解為有且只有一個后台線程對多個業務線程進行定時定頻率調度
TimerTask可以理解為業務邏輯的編寫
即:Timer按照一定的時間頻率調度TimerTask里面的業務邏輯。
下面,通過實現怎么讓程序在2秒后執行,來說明實現Timer調度的代碼編寫:
Timer timer=new Timer(); Calendar calendar =Calendar.getInstance(); SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("當前時間是 "+sf.format(calendar.getTime())); timer.schedule(new TimerTask(){ public void run(){ Calendar calendar =Calendar.getInstance(); SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("執行此次任務的時間是 "+sf.format(calendar.getTime())); } },2000);
可見,是通過實例化Timer,調用其的schedule方法來實現定時調度的。
schedule有以下四種形式:
schedule(task,time);
schedule(task,time,period);
schedule(task,delay);
schedule(task,delay,period);
其中,task是我們需要執行的任務,time是首次執行任務的時刻,period是執行一次task的時間間隔,delay是執行第一次任務前的延遲時間,單位均為毫秒。
那么最后就是編寫task代碼了
在這里,用一個內部類來說明,我們通過重寫run方法的方式來編寫自己的任務代碼。
以上基本實現了定時定頻率調度任務。
不過,有兩個問題:
1.如果我們需要任務執行的時間,在當前時間之前,會發生什么?
2.如果我們任務的執行時間大於任務的執行間隔,會發生什么?
對於問題一,我們可以將上面的run方法稍加修改就可以知道了:
public void run(){ Calendar calendar =Calendar.getInstance(); SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); calendar.add(Calendar.SECOND, -1); System.out.println("執行此次任務的時間是 "+sf.format(calendar.getTime())); }
得出得結果是這樣的:
當前時間是 2017-05-21 10:25:14
執行此次任務的時間是 2017-05-21 10:25:15
在我將程序中時間倒退了一秒的情況下,程序選擇立刻執行並且還是會考慮延遲的。
對於問題二,也可以簡單驗證;
timer.schedule(new TimerTask(){
public void run(){ Calendar calendar =Calendar.getInstance(); SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("執行此次任務的時間是 "+sf.format(calendar.getTime())); } },1000,2000);
輸出結果:
當前時間是 2017-05-21 10:31:05
執行此次任務的時間是 2017-05-21 10:31:06
執行此次任務的時間是 2017-05-21 10:31:09
執行此次任務的時間是 2017-05-21 10:31:12
是不是和想的一樣,程序會相對於上一次執行完成的時間點開始執行,然后慢慢滯后。
討論完了,schedule方法,其實Timer里面還有一個可以實現任務調度的方法,scheduleAtFixedRate,
scheduleAtFixedRate(task,time,period);
scheduleAtFixedRate(task,delay,period);
不考慮上面那兩個問題的話,執行過程差不多,相對於那兩種情況,因為scheduleAtFixedRate執行過程存在一定的並發性,在實際執行過程中小白感覺比較復雜,不討論了。。。
最后簡單說下,
Timer里面的其它重要方法:
cancel(),終止此計時器,丟棄所有當前已安排的任務,也可單獨取消,如task1.cancel();
purge(),從此計時器的任務隊列中移除所有已取消的任務,返回從隊列中移除的任務數。
TimeTask里面的其它重要方法:
cancel(),取消當前TimeTask里的任務;
scheduledExecutionTime(),返回此任務最近實際執行的已安排執行的時間。