Timer是JDK中的定時調度類,主要用來定時觸發任務:
- 用法:
Timer是調度控制器,TimerTask是可調度的任務:
1: import java.util.Date;
2: import java.util.TimerTask;
3:
4: public class PlainTimerTask extends TimerTask {
5:
6: @Override
7: public void run() {
8: System.out.println(new Date());
9:
10: }
11:
12: }
13:
調度過程:
1: import java.util.Timer;
2:
3: public class TimerRunner {
4:
5: public static void main(String [] args){
6: Timer timer=new Timer();
7: timer.schedule(new PlainTimerTask(), 5000L);
8: }
9:
10: }
2.原理:
其基本處理模型是單線程調度的任務隊列模型,Timer不停地接受調度任務,所有任務接受Timer調度后加入TaskQueue,TimerThread不停地去TaskQueue中取任務來執行.
從圖上不難看出,這就是生產者--消費者模型的一種特例:多生產者,單消費者模型。
此種消息隊列實現方式在瀏覽器中的編程模型中也有類似的實現,javascript中的定時執行函數setTimeout(expression,milliseconds)也是基於此種原理實現的。
此種方式的不足之處為當某個任務執行時間較長,以致於超過了TaskQueue中下一個任務開始執行的時間,會影響整個任務執行的實時性。為了提高實時性,可以采用多個消費者一起消費來提高處理效率,避免此類問題的實現。
3.核心代碼:
1: private void mainLoop() {
2: while (true) {
3: try {
4: TimerTask task;
5: boolean taskFired;
6: synchronized(queue) {
7: // Wait for queue to become non-empty
8: while (queue.isEmpty() && newTasksMayBeScheduled)
9: queue.wait();
10: if (queue.isEmpty())
11: break; // Queue is empty and will forever remain; die
12:
13: // Queue nonempty; look at first evt and do the right thing
14: long currentTime, executionTime;
15: task = queue.getMin();
16: synchronized(task.lock) {
17: if (task.state == TimerTask.CANCELLED) {
18: queue.removeMin();
19: continue; // No action required, poll queue again
20: }
21: currentTime = System.currentTimeMillis();
22: executionTime = task.nextExecutionTime;
23: if (taskFired = (executionTime<=currentTime)) {
24: if (task.period == 0) { // Non-repeating, remove
25: queue.removeMin();
26: task.state = TimerTask.EXECUTED;
27: } else { // Repeating task, reschedule
28: queue.rescheduleMin(
29: task.period<0 ? currentTime - task.period
30: : executionTime + task.period);
31: }
32: }
33: }
34: if (!taskFired) // Task hasn't yet fired; wait
35: queue.wait(executionTime - currentTime);
36: }
37: if (taskFired) // Task fired; run it, holding no locks
38: task.run();
39: } catch(InterruptedException e) {
40: }
41: }
42: }
1.先獲得隊列鎖,然后去TaskQueue中取TimerTask,然后去判斷此隊列為空且新任務可安排標記是打開的。如果不滿足,線程等待,將隊列鎖釋放。
2.如果隊列為空,那么跳出死循環。
3.取得隊列中的下一個元素,並獲得任務鎖。
4.檢查任務狀態,如果任務狀態為取消,那么直接取消,並跳過此輪循環。
5.得到任務的計划執行時間,並檢查與當前時間的先后,如果當前時間已經到或者超過計划執行時間,那么置狀態位為執行。
6.釋放任務鎖。
7.如果沒有,線程等待執行時間和當前時間差。
8.釋放隊列鎖
9.看任務是否可以執行標記,來確定是否執行任務
10反復從1開始