【Java定時任務調度工具】Timer

筆記來源: IMOOC Java Timer

定時任務調度

  • 基於給定的時間點給定的時間間隔或者給定的執行次數自動執行的任務。

Timer 定義

  • 一種工具,線程用其安排之後在後臺線程中執行的任務。可安排任務執行一次,或者按期重複執行。
  • 有且僅有一個後臺線程多個業務線程進行定時定頻率的調度

Timer 主要構建

Timer主要構建

Timer 主要成分

Timer主要成分

Timer 定時調度函數

schedule 的四種用法

  1. schedule(task, time)html

    • 參數java

      • task - 所要安排的任務
      • time - 執行任務的時間
    • 做用android

      • 在時間等於或超過time的時候執行且僅執行一次task
  2. schedule(task, time, period)併發

    • 參數app

      • task - 所要安排的任務
      • time - 首次執行任務的時間
      • period - 執行一次task的時間間隔,單位是毫秒
    • 做用ide

      • 時間等於或超過time時首次執行task,以後每隔period毫秒重複執行一次task
  3. schedule(task, delay)函數

    • 參數工具

      • task - 所要安排的任務
      • delay - 執行任務前的延遲時間,單位是毫秒
    • 做用this

      • 等待delay毫秒後執行且僅執行一次task
  4. schedule(task, delay, period)spa

    • 參數

      • task - 所要安排的任務
      • delay - 執行任務前的延遲時間,單位是毫秒
      • period - 執行一次task的時間間隔,單位是毫秒
    • 做用

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

scheduleAtFixedRate 的兩種用法

  1. scheduleAtFixedRate(task, time, period)

    • 參數

      • task - 所要安排的任務
      • time - 首次執行任務的時間
      • period - 執行一次task的時間間隔,單位是毫秒
    • 做用

      • 時間等於或超過time時首次執行task,以後每隔period毫秒重複執行一次task
  2. scheduleAtFixedRate(task, delay, period)

    • 參數

      • task - 所要安排的任務
      • delay - 執行任務前的延遲時間,單位是毫秒
      • period - 執行一次task的時間間隔,單位是毫秒
    • 做用

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

Timer 示例

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() {
        // 以 yyyy-MM-dd HH:mm:ss 的格式打印當前執行時間
        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()));

        // 打印當前name的內容
        System.out.println("Current exec name is: " + name);
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;

public class MyTimer {
    public static void main(String[] args) {
        // 1. 建立一個timer實例
        Timer timer = new Timer();
        // 2. 建立一個MyTimerTask實例
        MyTimerTask myTimerTask = new MyTimerTask("No.1");
        /**
         * 獲取當前時間,並設置成距離當前時間三秒後的時間
         */
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("Current main time is: " + sf.format(calendar.getTime()));
        calendar.add(Calendar.SECOND, 3);
        // 3. 經過timer定時定頻率調用myTimerTask的業務邏輯
        //-------------------schedule的四種用法-------------------//
        /**
         * 在時間等於或超過time的時間執行且僅執行一次task
         */
        myTimerTask.setName("schedule_1");
        timer.schedule(myTimerTask, calendar.getTime());

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

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

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

        //--------------scheduleAtFixedRate的兩種用法-------------//
        /**
         * 時間等於或超過time時首次執行task,以後每隔period毫秒重複執行一次task
         */
        myTimerTask.setName("scheduleAtFixedRate_1");
        timer.scheduleAtFixedRate(myTimerTask, calendar.getTime(), 2000);

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

schedule 與 scheduleAtFixedRate 的區別

首次計劃執行的時間早於當前的時間

  1. schedule 方法

    • fixed-delay;若是第一次執行時間被 delay 了,隨後的執行時間按照上一次實際執行完成的時間點進行計算
  2. scheduleAtFixedRate 方法

    • fixed-rate;若是第一次執行時間被 delay 了,隨後的執行時間按照上一次開始的時間點進行計算,而且爲了遇上進度會屢次執行任務,所以 TimerTask 中的執行體須要考慮同步

任務執行所需時間超出任務的執行週期間隔

  1. schedule 方法

    • 下一次執行時間相對於上一次實際執行完成的時間點,所以執行時間會不斷延後
  2. scheduleAtFixedRate 方法

    • 下一次執行時間相對於上一次開始的時間點,所以執行時間通常不會延後,所以存在併發性

其餘重要函數

  • TimerTaskcancel()scheduleExecutionTime()
  • Timercancel()purge()

TimerTask 的兩個重要函數

  • cancel()

    • 做用:取消當前 TimerTask 裏的任務
  • scheduleExecutionTime()

    • 做用:返回此任務最近實際執行的已安排執行的實際
    • 返回:最近發生此任務執行安排的時間,爲Long類型

Timer 的其餘函數

  • cancel()

    • 終止此計時器,丟棄全部當前已安排的任務
  • purge()

    • 做用:今後計時器的任務隊列中移除全部已取消的任務
    • 返回:從隊列中移除的任務數

Timer 函數的綜合應用

  • 模擬兩個機器人的定時行爲

    • 第一個機器人會隔兩秒打印最近一次計劃的時間、執行內容
    • 第二個機器人會模擬往桶裏倒水,直到桶裏的水滿爲止,而後中止工做
    • 桶裏的水滿了以後,第一個機器人再跳舞兩秒鐘,而後中止工做
/**
 * 跳舞的機器人
 */
public class DancingRobot extends TimerTask {
    @Override
    public void run() {
        // 獲取最近的一次任務執行的時間,並將其格式化
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("Scheduled exec time is: " + sf.format(scheduledExecutionTime()));
        System.out.println("Dancing happily!");
    }
}

/**
 * 倒水的機器人
 */
public class WaterRobot extends TimerTask {
    private Timer timer;
    // 最大容量爲5L
    private Integer bucketCapacity = 0;
    public WaterRobot(Timer inputTimer) {
        timer = inputTimer;
    }
    @Override
    public void run() {
        // 灌水直接至桶滿爲止
        if(bucketCapacity < 5){
            System.out.println("Add 1L water into the bucket!");
            bucketCapacity ++;
        } else {
            // 水滿以後就中止執行
            System.out.println("The number of canceled task in timer is: " + timer.purge());
            cancel();
            System.out.println("The waterRobot has been aborted");
            System.out.println("The number of canceled task in timer is: " + timer.purge());
            System.out.println("Current water is " + bucketCapacity + "L");
            // 等待兩秒鐘,終止timer裏面的全部內容
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            timer.cancel();
        }
    }
}

public class Executor {
    public static void main(String[] args) {
        Timer timer = new Timer();
        // 獲取當前時間
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("Current time is: " + sf.format(calendar.getTime()));

        DancingRobot dr = new DancingRobot();
        WaterRobot wr = new WaterRobot(timer);

        timer.schedule(dr, calendar.getTime(), 2000);
        timer.scheduleAtFixedRate(wr, calendar.getTime(), 1000);
    }
}

Timer 的缺陷

  • 管理併發任務的缺陷

    • Timer 有且只有一個線程去執行定時任務,若是存在多個任務,且任務時間過長,會致使執行效果與預期不符
  • 當任務拋出異常時的缺陷

    • 若是 TimerTask 拋出 RuntimeException,Timer 會中止全部任務的運行

Timer 的使用禁區

  • 對時效性要求較高的多任務併發做業
  • 對複雜的任務的調度

擴展閱讀

相關文章
相關標籤/搜索