1. 程式人生 > >任務排程(一)——jdk自帶的Timer

任務排程(一)——jdk自帶的Timer

 

https://blog.csdn.net/xiaoxian8023/article/details/45569441

 

 

說到任務排程,大家可能會想到Quartz框架,但是jdk自帶的簡單任務排程工具類,反而瞭解的人並不是很多。我覺得如果你的業務相對簡單的話,沒必要非得用Quartz等框架,使用Timer完全可以勝任的。簡單來分享一下我瞭解的Timer。

 

  Timer是jdk中提供的一個定時器工具,使用的時候會在主執行緒之外起一個單獨的執行緒執行指定的計劃任務,可以指定執行一次或者反覆執行多次。

  TimerTask是一個實現了Runnable介面的抽象類,代表一個可以被Timer執行的任務。

 

       我是用TimerTask來建立一個任務,其中run方法裡是任務排程的邏輯。使用一個Timer物件來排程任務。

 

       首先給一個特別簡單的示例:

 

 
  1. package com.tgb.ccl.schema;

  2.  
  3. import java.util.Date;

  4. import java.util.TimerTask;

  5.  
  6. /**

  7. * 不可動態修改的任務

  8. *

  9. * @author arron

  10. * @date 2015年5月7日 下午1:52:15

  11. * @version 1.0

  12. */

  13. public class FixedTimerTask extends TimerTask{

  14.  
  15. @Override

  16. public void run() {

  17. Date d = new Date();

  18. for(int i=0;i<3;i++){

  19. try {

  20. Thread.sleep(1000);

  21. System.out.println("已執行【"+(i+1)+"】秒鐘,at: "+d.toLocaleString());

  22. } catch (InterruptedException e) {

  23. e.printStackTrace();

  24. }

  25. }

  26. System.out.println("本次任務排程結束,at: "+new Date().toLocaleString());

  27. System.out.println("---------------------------");

  28. }

  29.  
  30. }

 

 
  1. package com.tgb.ccl.schema;

  2.  
  3. import java.util.Calendar;

  4. import java.util.Date;

  5. import java.util.Timer;

  6.  
  7. /**

  8. * 任務排程管理器

  9. *

  10. * @author arron

  11. * @date 2015年5月7日 下午1:57:19

  12. * @version 1.0

  13. */

  14. public class TaskManager {

  15. // private static final long PERIOD = 5 * 60 * 1000;// 5分鐘

  16. private static final long PERIOD = 5 * 1000;// 1秒鐘

  17.  
  18. public TaskManager() {

  19. Timer timer = new Timer();

  20. FixedTimerTask task = new FixedTimerTask();

  21. System.out.println("start");

  22.  
  23.  
  24. //0表示立即執行一次,以後每隔一段時間執行一次

  25. timer.schedule(task, 0, PERIOD);

  26.  
  27. //1000表示1秒後執行一次,以後每隔一段時間執行一次

  28. //timer.schedule(task, 1000, PERIOD);

  29.  
  30. //0表示立即執行一次,以後每隔一段時間執行一次

  31. //timer.schedule(task, 1000, PERIOD);

  32.  
  33. // 在當天14點4分整,執行一次,以後不再執行

  34. //timer.schedule(task, bookTime(15,0,0));

  35.  
  36. //在當天14點4分整,執行一次,以後每隔一段時間執行一次

  37. //如果時間超過了設定時間,會立即執行一次

  38. // timer.schedule(task, bookTime(0,34,10),PERIOD);

  39. // timer.scheduleAtFixedRate(task, bookTime(0,40,0),PERIOD);

  40.  
  41. }

  42.  
  43.  
  44. private Date bookTime(int hour, int minute, int second) {

  45. Calendar calendar = Calendar.getInstance();

  46. calendar.set(Calendar.HOUR_OF_DAY, hour);

  47. calendar.set(Calendar.MINUTE, minute);

  48. calendar.set(Calendar.SECOND, second);

  49. Date date = calendar.getTime();

  50. return date;

  51. }

  52.  
  53. public static void main(String[] args) {

  54. new TaskManager();

  55. }

  56. }

 

       只要執行main方法就可以測試了。

 

       大家可能已經注意到了,timer的schedule方法是過載的。引數主要有必須有一個TimerTask例項。第二個引數如果是long型別的,這個引數則是表示延遲時間,以毫秒為單位。如果為1000,那就是1秒後執行任務排程。如果是Date型別,則表示設定任務開始執行的時刻。當時間到達這個時刻,那麼任務會自動開始排程。當然如果當前時間已經超過了設定的開始時間,那麼會立即執行一次。第三個引數則是可選引數,是long型別的引數,表示排程的間隔時間。如果有這個引數,表示任務是重複性的排程。否則只會執行一次。這個引數依舊以毫秒為單位。

 

       如果你稍微注意一下,就會發現timer不只提供了schedule方法,還提供了scheduleAtFixedRate方法。這兩個方法都是任務排程方法,他們有什麼區別呢?


       區別在於噹噹前時間已經超過了設定執行時間,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方法的測試效果)

       這個跟網上很多人說的不太一樣。不過這個是我測試出來了。他們說的那種結果反正我是測不出來。具體你相信哪種,你自己試過就清楚了。