java關於Timer schedule執行定時任務


1、在應用開發中,經常需要一些周期性的操作,比如每5分鍾執行某一操作等。對於這樣的操作最方便、高效的實現方式就是使用java.util.Timer工具類。

private java.util.Timer timer; 
timer = new Timer(true); 
timer.schedule(
new java.util.TimerTask() { public void run() { //server.checkNewMail(); 要操作的方法 } }, 0, 5*60*1000); 
      第一個參數是要操作的方法,第二個參數是要設定延遲的時間,第三個參數是周期的設定,每隔多長時間執行該操作。

    使用這幾行代碼之后,Timer本身會每隔5分鍾調用一遍server.checkNewMail()方法,不需要自己啟動線程。Timer本身也是多線程同步的,多個線程可以共用一個Timer,不需要外部的同步代碼。

 
2、
(1)Timer.schedule(TimerTask task,Date time)安排在制定的時間執行指定的任務。
(2)Timer.schedule(TimerTask task,Date firstTime ,long period)安排指定的任務在指定的時間開始進行重復的固定延遲執行.
(3)Timer.schedule(TimerTask task,long delay)安排在指定延遲后執行指定的任務.
(4)Timer.schedule(TimerTask task,long delay,long period)安排指定的任務從指定的延遲后開始進行重復的固定延遲執行.
(5)Timer.scheduleAtFixedRate(TimerTask task,Date firstTime,long period)安排指定的任務在指定的時間開始進行重復的固定速率執行.
(6)Timer.scheduleAtFixedRate(TimerTask task,long delay,long period)安排指定的任務在指定的延遲后開始進行重復的固定速率執行.
 
 

java timer 定時器

以下內容根據 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就定下來了。說白了,這個方法更注重保持執行頻率的穩定。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM