1. 程式人生 > 實用技巧 >拾遺Timer定時器

拾遺Timer定時器

一 Timer 介紹

在開發中我們經常會遇到一些簡單定時任務的需求,而不需要量級較重的定時任務就可以採取java定時器;

java.util.Timer工具類中的Timer 是定時器,但定時任務寫在java.util.TimerTask 中,由 Timer 執行 TimerTask ;

Timer 的本質就是執行緒,構造方法如下

public Timer(String name) {
        thread.setName(name);
        thread.start();
    }

從原始碼角度可知,如果這樣建立定時器非守護執行緒,即使主執行緒執行結束,定時任務還是會執行;如果我們會使用如下的構造方式建立定時任務就是守護執行緒方式,會隨著主執行緒的消亡而消亡;

public Timer(String name, boolean isDaemon) {
        thread.setName(name);
        thread.setDaemon(isDaemon);
        thread.start();
    }

Timer內部維護了一個優先佇列,用於順序執行TimerTask任務;

private final TaskQueue queue = new TaskQueue();
private final TimerThread thread = new TimerThread(queue);

優先佇列的實現就是陣列方式作為平衡二叉堆

private TimerTask[] queue = new TimerTask[128];

TimerTask 實現了Runnable 介面,執行的任務動作就是run方法;

public abstract class TimerTask implements Runnable {
	// ....
	    protected TimerTask() {
    }

    public abstract void run();
	//....
}

所以定時器的本質就是啟動了一個新的執行緒執行任務,這些任務都會維護在優先佇列裡面

timer的排程主要方法如下

  • schedule(TimerTask task, long delay) 延遲 delay 毫秒執行一次
  • schedule(TimerTask task, Date time) 指定時間執行一次
  • schedule(TimerTask task, long delay, long period) 延遲delay毫秒以後,每隔period毫秒執行一次
  • schedule(TimerTask task, Date firstTime, long period) 從firstTime時刻開始,每隔period毫秒執行一次

二 Timer使用示例

如果方式簡單使用Timer去延遲執行執行緒任務,當然其它四種方法同理,呼叫方式區別不大;

    public static void main(String[] args) {
        // 建立定時器
        Timer timer = new Timer("知識追尋者");
        // 建立定時器任務;實現run 方法
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                System.out.println("執行緒執行了"+ LocalTime.now());
            }
        };
        System.out.println("程式執行時間"+ LocalTime.now());
        // 啟動定時器
        timer.schedule(timerTask,5000);
    }

輸出的間隔大約就是5秒

程式執行時間 18:47:28.258
執行緒執行了18:47:33.259

三 cancel 方法

TimerTask的cancel () 方法是將自身任務從任務佇列中移除

我們先延遲2秒,再每2秒執行一次看效果

    public static void main(String[] args) {
        // 建立定時器
        Timer timer = new Timer("知識追尋者");
        // 建立定時器任務;實現run 方法
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                System.out.println("執行緒執行了"+ LocalTime.now());
            }
        };
        System.out.println("程式執行時間"+ LocalTime.now());
        // 啟動定時器
        timer.schedule(timerTask,2000,2000);
    }

結果是每2秒會執行一次

程式執行時間18:59:23.557
執行緒執行了18:59:25.558
執行緒執行了18:59:27.558
執行緒執行了18:59:29.559

啟用cancel方法,後 就只會執行一次

    public static void main(String[] args) {
        // 建立定時器
        Timer timer = new Timer("知識追尋者");
        // 建立定時器任務;實現run 方法
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                System.out.println("執行緒執行了"+ LocalTime.now());
                // 呼叫 cancel方法
                this.cancel();
            }
        };
        System.out.println("程式執行時間"+ LocalTime.now());
        // 啟動定時器
        timer.schedule(timerTask,2000,2000);
    }

輸出如下

程式執行時間19:02:12.770
執行緒執行了19:02:14.772

Timer的cancel方法是移除所有的任務;

    public static void main(String[] args) {
        // 建立定時器
        Timer timer = new Timer("知識追尋者");
        // 建立定時器任務;實現run 方法
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                System.out.println("執行緒執行了"+ LocalTime.now());
            }
        };
        System.out.println("程式執行時間"+ LocalTime.now());
        timer.cancel();
        // 啟動定時器
        timer.schedule(timerTask,2000,2000);
    }

輸出直接報錯

程式執行時間:19:34.294
Exception in thread "main" java.lang.IllegalStateException: Timer already cancelled.
	at java.util.Timer.sched(Timer.java:397)
	at java.util.Timer.schedule(Timer.java:248)
	at com.youku1327.base.timer.TimerAbsolute.main(TimerAbsolute.java:28)

四 scheduleAtFixedRate

schedule 與 scheduleAtFixedRate 方法的區別如下:

schedule 方法如果執行任務的時間沒有被延遲,下一次執行任務時間參考的是上一次任務執行的開始時間

scheduleAtFixedRate 方法如果執行任務的時間沒有被延遲,下一次執行任務時間參考的是上一次任務執行的結束時間

五 Timer缺點

  • Timer 對排程的支援是基於絕對時間的,而不是相對時間,所以它對系統時間的改變非常敏感。
  • Timer 執行緒是不會捕獲異常的,如果 TimerTask 丟擲的了未檢查異常則會導致 Timer 執行緒終止。

關注公眾號:回覆 拍拍知識追尋者,領取面試資料和原創PDF教程;