Java定時任務排程工具Timer詳解
阿新 • • 發佈:2018-11-26
做專案很多時候會用到定時任務,比如在深夜,流量較小的時候,做一些統計工作。早上定時傳送郵件,更新資料庫等。
這裡可以用Java的Timer或執行緒池實現。
Timer可以實現,不過Timer存在一些問題。他起一個單執行緒,如果有異常產生,執行緒將退出,整個定時任務就失敗。
Timer定時任務原理基本理解:單執行緒 + 最小堆 + 不斷輪詢
Timer有四種用法
四種用法,通過其引數名稱也可以瞭解到具體含義,下面舉例子來實現其功能:
import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.SimpleTimeZone; import java.util.TimerTask; public class MyTimerTask extends TimerTask { private String name; private Integer count= 0; public MyTimerTask(String inputName){ name=inputName; } //建立MyTimerTask類,實線其run方法 @Override public void run(){ if(count<3){ Calendar calendar =Calendar.getInstance(); SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("Current exec time is :"+sf.format(calendar.getTime())); System.out.println("Current name is:"+name); count++; } else { //結束 cancel(); System.out.println("The task is cancel"); } } public String getName() { return name; } public void setName(String name) { this.name = name; } }
下面具體呼叫task幾種用法,可以執行檢視效果,具體實現功能在註釋中有介紹。
import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Timer; public class MyTimer { public static void main(String[] args) { //1.建立一個Timer例項 Timer timer =new Timer(); //2.建立一個MyTimerTask例項 MyTimerTask myTimerTask =new MyTimerTask("No.1"); Calendar calendar =Calendar.getInstance(); SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("Current exec time is :"+sf.format(calendar.getTime())); // 這裡獲得3s後的時間 calendar.add(Calendar.SECOND,3); //用法1: 1.到達指定時間時候或者超過time時間,執行且執行一次task任務 myTimerTask.setName("schedue1"); timer.schedule(myTimerTask,calendar.getTime()); //用法2:2.指定達到該定時時候首次執行task,之後間隔為period毫秒執行一次 myTimerTask.setName("schedule2"); timer.schedule(myTimerTask,calendar.getTime(),2000); //用法3:3.delay表示執行任務前的時間,執行一次task myTimerTask.setName("schedule3"); timer.schedule(myTimerTask,1000); //用法4:4.delay表示執行任務前的時間,執行一次task的時間間隔,類似第二種用法 myTimerTask.setName("schedule4"); timer.schedule(myTimerTask,1000,3000); //delay表示執行任務前的時間,執行一次task的時間間隔,類似第二種用法 myTimerTask.setName("scheduleAtFixedRate1"); //scheduleAtFixedRate用法和schedule用法類似,兩種,分別類似2和4兩種用法 timer.scheduleAtFixedRate(myTimerTask,calendar.getTime(),3000); } }
cancel()用在具體MyTaskTimer裡,終止的是其中具體事例的task,如果直接呼叫timer裡面的timer.cancel()則終止了所有的task。
這裡也可以將MyTaskTimer寫成內部類,就不用寫兩個類了。
scheduleAtFixedRate和schedule的區別
具體場景 | schedule | scheduleAtFixedRate |
1、首次計劃執行時間早於當前時間 | 按照上一次實際執行完成的時間點來進行計算 | 按照上一次開始的時間點進行計算,並且為了趕上進度會多次執行任務,在TimerTask的執行中需要考慮同步 |
2、任務執行所需時間超出任務執行週期間隔 | 下一次執行時間相對於上一次實際執行完成的時間點,執行時間不斷延後 | 下一次執行時間相對於上一次開始的時間點,執行時間一般不會延後,因此存在併發性 |
Timer缺陷和使用禁區
1、在管理併發任務時候的缺陷:
Timer僅有一個執行緒去執行定時任務,如果存在多個任務,且任務時間比較長,則會產生和預期效果不符的情況。
2、處理丟擲異常時候的缺陷:
如果TimeTask丟擲RuntimeException,Timer就會停止所有任務的執行。
根據其缺陷,我們在使用時候注意,以下情況就不用Timer了,需要用到Quartz:
1、對時效性要求較高的多工併發作業
2、對複雜的任務的排程