Java定時器之Timer學習一

Timer 的定義

有且僅有一個後臺線程對多個業務進行定時定頻的調度。Timer 類能夠保證多個線程能夠共享單個 Timer 對象而無需進行外部同步,因此 Timer 類是線程安全的。java

核心的兩個類

java.util.Timer java.util.TimerTask安全

java.util.Timer。其實是個線程,定時調度所擁有的 TimerTasks.ide

一個 TimerTask 實際上就是一個擁有 run() 方法的類,須要定時執行的代碼放到run方法體內,TimerTask 通常是以匿名類的方式建立。
TimerTask 類是一個定時任務類,該類實現了 Runnable 接口,並且是一個抽象類測試

說明

java.util.TimerTaskthis

TimerTask 類是一個抽象類,由 Timer 安排爲一次執行或重複執行的任務。線程

/* TimerTask 的類定義,爲抽象類,而且實現了 Runnable 
   能夠經過繼承該類,來實現本身的定時任務。*/
public abstract class TimerTask implements Runnable

它有一個抽象方法 run() 方法,該方法用於執行相應計時器任務要執行的操做。所以每個具體的任務類都必須繼承 TimerTask,而後重寫 run() 方法。
另外它還有兩個非抽象的方法:code

  • boolean cancel():取消此計時器任務。
  • long scheduledExecutionTime():返回此任務最近實際執行的安排執行時間。

java.util.Timerorm

注意:javax.swing 包中也有一個Timer類,若是import中用到swing包, 要注意名字的衝突。 對象

Timer 定時器實例有多種構造方法繼承

  •   Timer() : 建立一個新計時器。
  •   Timer(boolean isDaemon) :建立一個新計時器,能夠指定其相關的線程做爲守護程序運行。
  •   Timer(String name) :建立一個新計時器,其相關的線程具備指定的名稱。
  •   Timer(String name, boolean isDaemon):建立一個新計時器,其相關的線程具備指定的名稱,而且能夠指定做爲守護程序運行。

Timer 定時器的schedule() (調度方法)

下面例子部分參數說明:

delay: 延遲執行的毫秒數,即在delay毫秒以後第一次執行

period:重複執行的時間間隔

/* time爲Date類型:在指定時間執行一次。 */
timer.schedule(task, time); 

/* firstTime爲Date類型,period爲long 
 從firstTime時刻開始,每隔period毫秒執行一次。 */
timer.schedule(task, firstTime, period); 

/* delay 爲 long類型:從如今起過delay毫秒執行一次 */
timer.schedule(task, delay) 

/* delay 爲 long, period 爲 long:從如今起過delay毫秒之後,每隔 period  毫秒執行一次。*/
timer.schedule(task, delay, period)

方法名稱 schedule() 和 scheduleAtFixedRate() 的區別

  • schedule() 方法更注重保持間隔時間的穩定:保障每隔period時間可調用一次
  • scheduleAtFixedRate() 方法更注重保持執行頻率的穩定:保障屢次調用的頻率趨近於period時間,若是任務執行時間大於period,會在任務執行以後立刻執行下一次任務

scheduleAtFixedRate()

  • scheduleAtFixedRate(TimerTask task, Date firstTime, long period):安排指定的任務在指定的時間開始進行重複的固定速率執行。
  • scheduleAtFixedRate(TimerTask task, long delay, long period):安排指定的任務在指定的延遲後開始進行重複的固定速率執行。

實例代碼說明

MyTimerTask.java

做爲一個須要調度的任務類。

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimerTask;

public class MyTimerTask extends TimerTask {

    private String name;

    public MyTimerTask(String inputName) {
        name = inputName;
    }

    @Override
    public void run() {

        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("current exec time is:"+ sf.format(calendar.getTime()));
        
        // 重寫來自於 TimerTask 的 run()
        System.out.println("Current exec name is:" + name);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

MyTimer.java

測試調度 MyTimerTask

import java.util.Timer;

public class MyTimer {
    
    public static void main(String[] args) {
        // 建立一個 timer 實例
        Timer timer = new Timer();
        
        // 建立一個 MyTimerTask 實例
        MyTimerTask myTimerTask = new MyTimerTask("No.1");
        
        /* 經過 timer 定時定頻調用 myTimerTask的業務邏輯
         * 即第一次執行是在當前時間的兩秒以後,以後每隔一秒執行一次
         */
        timer.schedule(myTimerTask, 2000L, 1000L);
    }

}

輸出結果

current exec time is:2018-06-05 14:35:22
Current exec name is:No.1
current exec time is:2018-06-05 14:35:23
Current exec name is:No.1
current exec time is:2018-06-05 14:35:24
Current exec name is:No.1

schedule() 的用法

代碼緊跟着上面的例子來作。

在時間等於或者超過 time 的時候執行,且執行一次

/* 獲取當前時間,並設置成距離當前時間3秒以後的時間
 * 好比當前時間爲: 2018-06-05 23:59:58
 * 則設置以後的時間爲: 2018-06-06 00:00:00
 */
Calendar calendar = Calendar.getInstance();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("current exec time is:"+ sf.format(calendar.getTime()));
calendar.add(Calendar.SECOND, 3);

/* 在時間等於或者超過 time 的時候執行,且執行一次 */
myTimerTask.setName("schedule1");
timer.schedule(myTimerTask, calendar.getTime());

輸出的結果爲:

current exec time is:2018-06-05 15:46:16
current exec time is:2018-06-05 15:46:19
Current exec name is:schedule1

時間等於或超過 time 的時候首次執行,以後每隔 period 毫秒重複執行一次 task

/* 獲取當前時間,並設置成距離當前時間3秒以後的時間
 * 好比當前時間爲: 2018-06-05 23:59:58
 * 則設置以後的時間爲: 2018-06-06 00:00:00
 */
Calendar calendar = Calendar.getInstance();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("current exec time is:"+ sf.format(calendar.getTime()));
calendar.add(Calendar.SECOND, 3);

/**
 * 時間等於或超過 time 的時候首次執行,以後每隔 period 毫秒重複執行一次 task
 */
myTimerTask.setName("schedule2");
timer.schedule(myTimerTask, calendar.getTime(), 3000L);

輸出的結果爲:

current exec time is:2018-06-05 15:54:32
current exec time is:2018-06-05 15:54:35
Current exec name is:schedule2
current exec time is:2018-06-05 15:54:38
Current exec name is:schedule2
current exec time is:2018-06-05 15:54:41
Current exec name is:schedule2

等待 delay 毫秒以後執行且執行一次 task

/**
 * 等待 delay 毫秒以後執行且執行一次 task
 */
myTimerTask.setName("schedule3");
timer.schedule(myTimerTask, 1000);

輸出結果爲:

current exec time is:2018-06-05 16:00:06
current exec time is:2018-06-05 16:00:07
Current exec name is:schedule3

等待 delay 毫秒以後,首次執行,而且以後每隔 period 毫秒重複執行一次 task

/**
 * 等待 delay 毫秒以後,首次執行,而且以後每隔 period 毫秒重複執行一次 task
 */
myTimerTask.setName("schedule4");
timer.schedule(myTimerTask, 1000, 3000);

輸出結果爲:

current exec time is:2018-06-05 16:01:36
current exec time is:2018-06-05 16:01:37
Current exec name is:schedule4
current exec time is:2018-06-05 16:01:40
Current exec name is:schedule4
current exec time is:2018-06-05 16:01:43
Current exec name is:schedule4

scheduleAtFixedRate() 的用法

時間等於或者超過 time 時首次執行 task,以後每隔 period 毫秒重複執行一次

/* 獲取當前時間,並設置成距離當前時間3秒以後的時間
 * 好比當前時間爲: 2018-06-05 23:59:58
 * 則設置以後的時間爲: 2018-06-06 00:00:00
 */
Calendar calendar = Calendar.getInstance();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("current exec time is:"+ sf.format(calendar.getTime()));
calendar.add(Calendar.SECOND, 3);

/* 時間等於或者超過 time 時首次執行 task,以後每隔 period 毫秒重複執行一次 */
myTimerTask.setName("scheduleAtFixedRate1");
timer.scheduleAtFixedRate(myTimerTask, calendar.getTime(), 3000);

輸出的結果爲:

current exec time is:2018-06-05 16:11:48
current exec time is:2018-06-05 16:11:51
Current exec name is:scheduleAtFixedRate1
current exec time is:2018-06-05 16:11:54
Current exec name is:scheduleAtFixedRate1
current exec time is:2018-06-05 16:11:57
Current exec name is:scheduleAtFixedRate1

等待 delay 毫秒以後,首次執行,而且以後每隔 period 毫秒重複執行一次 task

/* 等待 delay 毫秒以後,首次執行,而且以後每隔 period 毫秒重複執行一次 task */
myTimerTask.setName("scheduleAtFixedRate2");
timer.scheduleAtFixedRate(myTimerTask, 1000, 3000);

輸出的結果爲:

current exec time is:2018-06-05 16:15:47
current exec time is:2018-06-05 16:15:48
Current exec name is:scheduleAtFixedRate2
current exec time is:2018-06-05 16:15:51
Current exec name is:scheduleAtFixedRate2
current exec time is:2018-06-05 16:15:54
Current exec name is:scheduleAtFixedRate2
相關文章
相關標籤/搜索