Timer主要用於Java線程裏指定時間或週期運行任務,它是線程安全的,但不提供實時性(real-time)保證。
上面提到了守護線程的概念。
Java分爲兩種線程:用戶線程和守護線程。
所謂守護線程,是指在程序運行的時候在後臺提供一種通用服務的線程,比如垃圾回收線程就是一個很稱職的守護者,並且這種線程並不屬於程序中不可或缺的部分。因 此,當所有的非守護線程結束時,程序也就終止了,同時會殺死進程中的所有守護線程。反過來說,只要任何非守護線程還在運行,程序就不會終止。
守護線程和用戶線程的唯一不同之處就在於虛擬機的離開:如果用戶線程已經全部退出運行了,只剩下守護線程存在了,虛擬機也就退出了。 因爲沒有了被守護者,守護線程也就沒有工作可做了,也就沒有繼續運行程序的必要了。
將線程轉換爲守護線程可以通過調用Thread對象的setDaemon(true)方法來實現。在使用守護線程時需要注意以下幾點:
(1) thread.setDaemon(true)必須在thread.start()之前設置,否則會跑出一個IllegalThreadStateException異常。你不能把正在運行的常規線程設置爲守護線程。
(2) 在Daemon線程中產生的新線程也是Daemon的。
(3) 守護線程應該永遠不去訪問固有資源,如文件、數據庫,因爲它會在任何時候甚至在一個操作的中間發生中斷。
我們接下來寫個案例,使得程序運行3秒後在控制檯打印輸出“該起牀了”。
package com.itszt.test7;
import java.text.SimpleDateFormat;
import java.util.Timer;
import java.util.TimerTask;
/**
* Java計時器
*/
public class TimerTest {
static String str="HH:mm:ss";
static SimpleDateFormat dateFormat = new SimpleDateFormat(str);
public static void main(String[] args) {
Timer timer = new Timer();
String now1 = dateFormat.format(System.currentTimeMillis());
System.out.println(now1);
//延遲3秒後執行任務
timer.schedule(new MyTask(),3000);//單位是毫秒
}
}
class MyTask extends TimerTask{
@Override
public void run() {
System.out.println("該起牀了");
String now2 = TimerTest.dateFormat.format(System.currentTimeMillis());
System.out.println(now2);
}
}
上述代碼執行後,延遲3秒打印出“該起牀了”,如下所示:
21:26:18
該起牀了
21:26:21
Timer的其他方法:
schedule(TimerTask task, Date time) 在指定的日期執行一次TimerTask任務;如果日期time早於當前時間,則立刻執行。
schedule(TimerTask task, long delay, long period) 以當前時間爲基準,延遲指定的毫秒後,再按指定的時間間隔地無限次數的執行TimerTask任務。
schedule(TimerTask task, Date firstTime, long period) 在指定的日期之後,按指定的時間間隔地無限次數的執行TimerTask任務。
scheduleAtFixedRate(TimerTask task, long delay, long period) 以當前時間爲基準,延遲指定的毫秒後,再按指定的時間間隔週期性地無限次數的執行TimerTask任務。