以下內容根據 The JavaTM Tutorial 和相關API doc翻譯整理,以供日後參考:
1.概覽
Timer是一種定時器工具,用來在一個後臺線程計劃執行指定任務。它可以計劃執行一個任務一次或反覆多次。
TimerTask一個抽象類,它的子類代表一個可以被Timer計劃的任務。
簡單的一個例程:
import java.util.Timer;
import java.util.TimerTask;
/** *//**
* Simple demo that uses java.util.Timer to schedule a task to execute
* once 5 seconds have passed.
*/
public class Reminder ...{
Timer timer;
public Reminder(int seconds) ...{
timer = new Timer();
timer.schedule(new RemindTask(), seconds*1000);
}
class RemindTask extends TimerTask ...{
public void run() ...{
System.out.println("Time's up!");
timer.cancel(); //Terminate the timer thread
}
}
public static void main(String args[]) ...{
System.out.println("About to schedule task.");
new Reminder(5);
System.out.println("Task scheduled.");
}
}
運行這個小例子,你會首先看到:
About to schedule task.
5秒鐘之後你會看到:
Time's up!
這個小例子可以說明一些用Timer線程實現和計劃執行一個任務的基礎步驟:
實現自定義的TimerTask的子類,run方法包含要執行的任務代碼,在這個例子裏,這個子類就是RemindTask。
實例化Timer類,創建計時器後臺線程。
實例化任務對象 (new RemindTask()).
制定執行計劃。這裏用schedule方法,第一個參數是TimerTask對象,第二個參數表示開始執行前的延時時間(單位是milliseconds,這裏定義了5000)。還有一種方法可以指定任務的執行時間,如下例,指定任務在11:01 p.m.執行:
//Get the Date corresponding to 11:01:00 pm today.
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 1);
calendar.set(Calendar.SECOND, 0);
Date time = calendar.getTime();
timer = new Timer();
timer.schedule(new RemindTask(), time);
2.終止Timer線程
默認情況下,只要一個程序的timer線程在運行,那麼這個程序就會保持運行。當然,你可以通過以下四種方法終止一個timer線程:
調用timer的cancle方法。你可以從程序的任何地方調用此方法,甚至在一個timer task的run方法裏。
讓timer線程成爲一個daemon線程(可以在創建timer時使用new Timer(true)達到這個目地),這樣當程序只有daemon線程的時候,它就會自動終止運行。
當timer相關的所有task執行完畢以後,刪除所有此timer對象的引用(置成null),這樣timer線程也會終止。
調用System.exit方法,使整個程序(所有線程)終止。
Reminder 的例子使用了第一種方式。在這裏不能使用第二種方式,因爲這裏需要程序保持運行直到timer的任務執行完成,如果設成daemon,那麼當main線程 結束的時候,程序只剩下timer這個daemon線程,於是程序不會等timer線程執行task就終止了。
有些時候,程序的終止與否 並不只與timer線程有關。舉個例子,如果我們使用AWT來beep,那麼AWT會自動創建一個非daemon線程來保持程序的運行。下面的代碼我們對 Reminder做了修改,加入了beeping功能,於是我們需要加入System.exit的調用來終止程序。
import java.util.Timer;
import java.util.TimerTask;
import java.awt.Toolkit;
/** *//**
* Simple demo that uses java.util.Timer to schedule a task to execute
* once 5 seconds have passed.
*/
public class ReminderBeep ...{
Toolkit toolkit;
Timer timer;
public ReminderBeep(int seconds) ...{
toolkit = Toolkit.getDefaultToolkit();
timer = new Timer();
timer.schedule(new RemindTask(), seconds*1000);
}
class RemindTask extends TimerTask ...{
public void run() ...{
System.out.println("Time's up!");
toolkit.beep();
//timer.cancel(); //Not necessary because we call System.exit
System.exit(0); //Stops the AWT thread (and everything else)
}
}
public static void main(String args[]) ...{
System.out.println("About to schedule task.");
new ReminderBeep(5);
System.out.println("Task scheduled.");
}
}
3.反覆執行一個任務
先看一個例子:
public class AnnoyingBeep ...{
Toolkit toolkit;
Timer timer;
public AnnoyingBeep() ...{
toolkit = Toolkit.getDefaultToolkit();
timer = new Timer();
timer.schedule(new RemindTask(),
0, //initial delay
1*1000); //subsequent rate
}
class RemindTask extends TimerTask ...{
int numWarningBeeps = 3;
public void run() ...{
if (numWarningBeeps > 0) ...{
toolkit.beep();
System.out.println("Beep!");
numWarningBeeps--;
} else ...{
toolkit.beep();
System.out.println("Time's up!");
//timer.cancel(); //Not necessary because we call System.exit
System.exit(0); //Stops the AWT thread (and everything else)
}
}
}
...
}
執行,你會看到如下輸出:
Task scheduled.
Beep!
Beep! //one second after the first beep
Beep! //one second after the second beep
Time's up! //one second after the third beep
這裏使用了三個參數的schedule方法用來指定task每隔一秒執行一次。如下所列爲所有Timer類用來制定計劃反覆執行task的方法 :
schedule(TimerTask task, long delay, long period)
schedule(TimerTask task, Date time, long period)
scheduleAtFixedRate(TimerTask task, long delay, long period)
scheduleAtFixedRate(TimerTask task, Date firstTime, long period)
當 計劃反覆執行的任務時,如果你注重任務執行的平滑度,那麼請使用schedule方法,如果你在乎的是任務的執行頻度那麼使用 scheduleAtFixedRate方法。 例如,這裏使用了schedule方法,這就意味着所有beep之間的時間間隔至少爲1秒,也就是說,如 果有一個beap因爲某種原因遲到了(未按計劃執行),那麼餘下的所有beep都要延時執行。如果我們想讓這個程序正好在3秒以後終止,無論哪一個 beep因爲什麼原因被延時,那麼我們需要使用scheduleAtFixedRate方法,這樣當第一個beep遲到時,那麼後面的beep就會以最快 的速度緊密執行(最大限度的壓縮間隔時間)。
4.進一步分析schedule和scheduleAtFixedRate
(1) 2個參數的schedule在制定任務計劃時, 如果指定的計劃執行時間scheduledExecutionTime<= systemCurrentTime,則task會被立即執行。scheduledExecutionTime不會因爲某一個task的過度執行而改變。
(2) 3個參數的schedule在制定反覆執行一個task的計劃時,每一次執行這個task的計劃執行時間隨着前一次的實際執行時間而變,也就是 scheduledExecutionTime(第n+1次)=realExecutionTime(第n次)+periodTime。也就是說如果第n 次執行task時,由於某種原因這次執行時間過長,執行完後的systemCurrentTime>= scheduledExecutionTime(第n+1次),則此時不做時隔等待,立即執行第n+1次task,而接下來的第n+2次task的 scheduledExecutionTime(第n+2次)就隨着變成了realExecutionTime(第n+1次)+periodTime。說 白了,這個方法更注重保持間隔時間的穩定。
(3)3個參數的scheduleAtFixedRate在制定反覆執行一個task的計劃時,每一次 執行這個task的計劃執行時間在最初就被定下來了,也就是scheduledExecutionTime(第n次)=firstExecuteTime +n*periodTime;如果第n次執行task時,由於某種原因這次執行時間過長,執行完後的systemCurrentTime>= scheduledExecutionTime(第n+1次),則此時不做period間隔等待,立即執行第n+1次task,而接下來的第n+2次的 task的scheduledExecutionTime(第n+2次)依然還是firstExecuteTime+(n+2)*periodTime這 在第一次執行task就定下來了。說白了,這個方法更注重保持執行頻率的穩定。
5.一些注意的問題
每一個Timer僅對應唯一一個線程。
Timer不保證任務執行的十分精確。
Timer類的線程安全的。
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/siyue_qi/archive/2008/05/22/2469316.aspx
Java Timer和TimerTask詳解
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.