2011年12月25日

Java Timer:排程、定時、週期性執行工作任務


 
在我們寫程式的時候,常常會需要定期、延遲、排程執行任務,
這個需求可以很簡單地利用 Java 1.3 之後的 java.util.Timer 來達成。

Timer 中只有下列幾個 method 可以使用,
cancel 是指取消執行工作並終止 timer,purge則是移除所有工作,
至於 schedule 和 scheduleAtFixedRate 就是用來排程執行的 method,
大家可以先看看各 method 的說明:
Modifier and TypeMethod and Description
voidcancel()
Terminates this timer, discarding any currently scheduled tasks.
intpurge()
Removes all cancelled tasks from this timer's task queue.
voidschedule(TimerTask task, Date time)
Schedules the specified task for execution at the specified time.
voidschedule(TimerTask task, Date firstTime, long period)
Schedules the specified task for repeated fixed-delay execution, beginning at the specified time.
voidschedule(TimerTask task, long delay)
Schedules the specified task for execution after the specified delay.
voidschedule(TimerTask task, long delay, long period)
Schedules the specified task for repeated fixed-delay execution, beginning after the specified delay.
voidscheduleAtFixedRate(TimerTask task, Date firstTime, long period)
Schedules the specified task for repeated fixed-rate execution, beginning at the specified time.
voidscheduleAtFixedRate(TimerTask task, long delay, long period)
Schedules the specified task for repeated fixed-rate execution, beginning after the specified delay.
看完了說明後接下來我們就來demo一下 Timer 該怎麼用!
首先我們需要自行撰寫一個繼承了 TimerTask 的 class,
其中必須覆寫 run(),並在裡面填上我們要執行的工作,
在這個例子中我們只是簡單地印出工作被執行當下的時間。
 1 package werdna1222coldcodes.blogspot.com.demo.timer;
 2 
 3 import java.util.*;
 4 
 5 public class DateTask extends TimerTask {
 6     
 7     @ Override
 8     public void run() {
 9         System.out.println("Task 執行時間:" + new Date());
10     }
11 }
接著則是測試程式 TimerDemo,在這個程式中我們測試了三種 schedule的語法:
首先 testScheduleDelay 只測試在 delay 3秒後啟動工作,
testScheduleDelayAndPeriod 除了 delay 3秒外,每2秒會重複執行工作,
testScheduleDateAndPeriod 則將 delay 改為精確的時間,每10秒重複工作。
 1 package werdna1222coldcodes.blogspot.com.demo.timer;
 2 
 3 import java.util.*;
 4 
 5 public class TimerDemo {
 6     public static void main(String[] args) {
 7 
 8         TimerDemo timerDemo = new TimerDemo();
 9         timerDemo.testScheduleDelay();
10         timerDemo.testScheduleDelayAndPeriod();
11         timerDemo.testScheduleDateAndPeriod();
12     }
13     
14     void testScheduleDelay(){
15 
16         Timer timer = new Timer();
17         System.out.println("Delay:3秒");
18         System.out.println("In testScheduleDelay:" + new Date());
19 
20         // schedule(TimerTask task, long delay)
21         timer.schedule(new DateTask(), 3000);
22         
23         try {
24             Thread.sleep(10000);
25         }
26             catch(InterruptedException e) {
27         }
28 
29         timer.cancel();
30         System.out.println("End testScheduleDelay:" 
31             + new Date() + "\n");
32     }
33     
34     void testScheduleDelayAndPeriod(){
35 
36         Timer timer = new Timer();
37         System.out.println("Delay:3秒, Period:2秒");
38         System.out.println("In testScheduleDelayAndPeriod:" 
39             + new Date());
40         
41         // schedule(TimerTask task, long delay, long period)
42         timer.schedule(new DateTask(), 3000, 2000);
43         
44         try {
45             Thread.sleep(10000);
46         }
47             catch(InterruptedException e) {
48         }
49 
50         timer.cancel();
51         System.out.println("End testScheduleDelayAndPeriod:" 
52             + new Date() + "\n");
53     }
54     
55     void testScheduleDateAndPeriod(){
56 
57         Timer timer = new Timer();
58         
59         // 設定填入schedule中的 Date firstTime 
60         為現在的15秒後
61         Calendar calendar = Calendar.getInstance();
62         calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND)+15)
63                      ;
64         Date firstTime = calendar.getTime();
65         
66         // 也可用 simpleDateFormat 直接設定 firstTime 
67         的精確時間
68         // SimpleDateFormat dateFormatter = 
69         //      new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");  
70         // Date firstTime = dateFormatter.parse("2011/12/25 13:30:00");
71         
72         System.out.println("In testScheduleDateAndPeriod:" 
73             + new Date());
74         System.out.println("設定執行 Date 為15秒後:" 
75             + firstTime +", Period:10秒");
76                 
77         // schedule(TimerTask task, Date firstTime, long period)
78         timer.schedule(new DateTask(), firstTime, 10000);
79                 
80         try {
81             Thread.sleep(30000);
82         }
83             catch(InterruptedException e) {
84         }
85 
86         timer.cancel();
87         System.out.println("End testScheduleDateAndPeriod:" 
88             + new Date() + "\n");
89     }
90 }

執行結果:
Delay:3秒
In testScheduleDelay:Sun Dec 25 13:32:47 CST 2011
Task 執行時間:Sun Dec 25 13:32:50 CST 2011
End testScheduleDelay:Sun Dec 25 13:32:57 CST 2011

Delay:3秒, Period:2秒
In testScheduleDelayAndPeriod:Sun Dec 25 13:32:57 CST 2011
Task 執行時間:Sun Dec 25 13:33:00 CST 2011
Task 執行時間:Sun Dec 25 13:33:02 CST 2011
Task 執行時間:Sun Dec 25 13:33:04 CST 2011
Task 執行時間:Sun Dec 25 13:33:06 CST 2011
End testScheduleDelayAndPeriod:Sun Dec 25 13:33:07 CST 2011

In testScheduleDateAndPeriod:Sun Dec 25 13:33:07 CST 2011
設定執行 Date 為15秒後:Sun Dec 25 13:33:22 CST 2011, Period:10秒
Task 執行時間:Sun Dec 25 13:33:22 CST 2011
Task 執行時間:Sun Dec 25 13:33:32 CST 2011
End testScheduleDateAndPeriod:Sun Dec 25 13:33:37 CST 2011
雖然 demo 只有三種,但其實大家應該可以很容易理解四種 API 的使用方式:
  1. schedule(TimerTask task, Date time): 在特定時間單次執行
  2. schedule(TimerTask task, Date firstTime, long period) :在特定時間後重複執行
  3. schedule(TimerTask task, long delay): 在特定 delay 後單次執行
  4. schedule(TimerTask task, long delay, long period): 在特定 delay 後重複執行
至於 schedule 和 scheduleAtFixedRate 有何不同,請見:
Java Timer:schedule和scheduleAtFixedRate有何不同
若想知道更多有關 Java 時間相關的轉換、排程等應用,請見:
Java 時間日期處理範例大全:含時間單位格式轉換、期間計算、排程等

關鍵字:java, timer, schedule, example, 例子, 範例, cancel, 停止, 取消, delay
參考資料:


更多精選推薦文章