1. 程式人生 > >Java定時器Timer學習筆記

Java定時器Timer學習筆記

1、 定時任務排程
基於給定的時間點,給定的時間間隔或者給定的執行次數自動執行的任務。

2、 Java中的定時任務排程工具:Timer和Quartz
Timer和Quartz區別:
1) Timer由JDK自身提供
2) Quartz時間控制功能更強大
3) 底層實現機制,Timer只有一個後臺執行緒去執行定時任務,而Quartz擁有後臺執行執行緒池,可以使用多個執行緒去執行定時任務。

3、 Timer的定義
有且僅有一個後臺執行緒對多個業務執行緒進行定時定頻率的排程。Timer可以簡單理解為排程執行緒,即後臺執行緒,TimerTask為業務執行緒。Timer定時呼叫TimerTask。
這裡寫圖片描述


這裡寫圖片描述

4、 Timer小Demo

public class MyTimerTask extends TimerTask{

    private String name;

    public MyTimerTask(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    @Override
public void run() { System.out.println("Current exec name is: " + name); } } public class MyTimer { public static void main(String[] args){ //1.建立一個Timer例項 Timer timer = new Timer(); //2.建立一個MyTimerTask例項 MyTimerTask myTimerTask = new MyTimerTask("No.1"
); //3.通過timer定時定頻率呼叫myTimerTask的業務邏輯 //即第一次執行是在當前時間的兩秒之後,之後每隔一秒鐘執行一次 timer.schedule(myTimerTask, 2000L, 1000L); } }

5、 schedule的4種用法和scheduleAtFixedRate兩種用法

public class MyTimerTask extends TimerTask{
    private String name;

    public MyTimerTask(String name){
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public void run() {
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("Current Time is: " + df.format(calendar.getTime()));
        System.out.println("My name is: " + name);
    }
}


public class MyTimer {

    public static void main(String[] args) {
        /** 1.建立一個Timer例項 **/
        Timer timer = new Timer();

        /** 2.建立一個MyTimerTask例項 **/
        MyTimerTask task = new MyTimerTask("lwh sayHello");

        /** 3.通過timer定時定頻率呼叫task **/
        //timer.schedule(task, 2000L, 1000L);

        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(df.format(calendar.getTime()));
        calendar.add(Calendar.SECOND, 3);

        /**
           schedule用法1
           public void schedule(TimerTask task, Date time)
           task任務,time首次執行任務的時間
           在時間等於或超過time的時候執行且僅執行一次task,如果所傳時間小於當前時間立即執行
         */
        //timer.schedule(task, calendar.getTime());

        /**
           schedule用法2
           public void schedule(TimerTask task, Date firstTime, long period)
           task任務,firstTime首次執行任務的時間,period執行一次task的時間間隔,單位毫秒
           在時間等於或超過time的時候首次執行task,之後每隔period毫秒重複執行一次task
         */
        //timer.schedule(task, calendar.getTime(), 2000L);

        /**
           schedule用法3
           public void schedule(TimerTask task, long delay)
           task任務,delay延遲時間
           等待delay毫秒之後執行且僅執行一次task
         */
        //timer.schedule(task, 1000L);

        /**
           schedule用法4
           public void schedule(TimerTask task, long delay, long period)
           task任務,delay延遲時間,period執行一次task的時間間隔
           等待delay毫秒之後首次執行task,之後每隔period毫秒重複執行一次task
         */
        //timer.schedule(task, 1000L, 3000L);

        /**
           scheduleAtFixedRate用法1
           public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)
           task任務,firstTime首次執行任務的時間,period執行一次task的時間間隔,單位毫秒
           在時間等於或超過time的時候首次執行task,之後每隔period毫秒重複執行一次task
         */
        //timer.scheduleAtFixedRate(task, calendar.getTime(), 2000L);

        /**
           scheduleAtFixedRate用法2
           public void scheduleAtFixedRate(TimerTask task, long delay, long period)
           task任務,delay延遲時間,period執行一次task的時間間隔
           等待delay毫秒之後首次執行task,之後每隔period毫秒重複執行一次task
         */
        timer.scheduleAtFixedRate(task, 2000L, 3000L);
    }
}

6、 TimerTask的兩個重要函式
1) cancel() 執行3次後取消定時任務

public class MyTimerTask extends TimerTask{
    private String name;

    private Integer count = 0;

    public MyTimerTask(String name){
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public void run() {
        if(count < 3){
            Calendar calendar = Calendar.getInstance();
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("Current Time is: " + df.format(calendar.getTime()));
            System.out.println("My name is: " + name);
            count++;
        }else {
            /** 取消當前TimerTask裡的任務 **/
            cancel();
            System.out.println("Task cancel");
        }

    }
}

2)scheduledExecutionTime() 返回此任務最近實際執行的已安排執行時間

timer.schedule(task, 4000L);
System.out.println("schedule time is: " + df.format(task.scheduledExecutionTime()));

這裡寫圖片描述

7、 Timer的其他重要函式
1) cancel() 終止此計時器,丟棄所有當前已安排的任務

2) purge() 從此計時器的任務佇列中移除所有已取消的任務,返回從佇列中移除的任務數

8、 schedule和scheduleAtFixedRate兩種情況看區別
1) 首次計劃執行的時間早於當前時間

public class ScheduleDiff {

    public static void main(String[] args) {
        final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();

        System.out.println("Current time is: " + df.format(calendar.getTime()));

        /** 設定成六秒之前的時間,若當前時間為2018-12-28 00:00:06,
            那麼設定之後的時間變成2018- 12-28 00:00:00 **/
        calendar.add(Calendar.SECOND, -6);

        Timer timer = new Timer();

        /** 第一次執行時間為6秒之前,隨後每隔兩秒執行一次 **/
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                /** 列印當前的計劃執行時間 **/
                System.out.println("Scheduled exec time is: " + df.format(scheduledExecutionTime()));

                System.out.println("Task is being executed!");
            }
        }, calendar.getTime(), 2000);
    }
}

這裡寫圖片描述

public class ScheduleFixRateDiff {

    public static void main(String[] args) {
        final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();

        System.out.println("Current time is: " + df.format(calendar.getTime()));

        /** 設定成六秒之前的時間,若當前時間為2018-12-28 00:00:06,
            那麼設定之後的時間變成2018-12-28 00:00:00 **/
        calendar.add(Calendar.SECOND, -6);

        Timer timer = new Timer();
        /** 第一次執行時間為6秒之前,隨後每隔兩秒執行一次 **/
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                /** 列印當前的計劃執行時間 **/
                System.out.println("Scheduled exec time is: " + df.format(scheduledExecutionTime()));
                System.out.println("Task is being executed!");
            }
        }, calendar.getTime(), 2000);

    }
}

這裡寫圖片描述

2) 任務所需的執行時間超出任務的執行間隔週期
schedule方法:下一次執行時間相對於上次實際執行完成的時間點,因此執行時間會不斷延後。看下面例子發現時間間隔其實變成了3秒。

public class ScheduleDiff {

    public static void main(String[] args) {
        final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();

        System.out.println("Current time is: " + df.format(calendar.getTime()));
        Timer timer = new Timer();
        /** 第一次執行時間為6秒之前,隨後每隔兩秒執行一次 **/
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                try{
                    /** 任務執行時間3秒 **/
                    Thread.sleep(3000);
                }catch (InterruptedException e){

                }
                /** 列印當前的計劃執行時間 **/
                System.out.println("Scheduled exec time is: " + df.format(scheduledExecutionTime()));
                System.out.println("Task is being executed!");
            }
        }, calendar.getTime(), 2000);

    }
}

這裡寫圖片描述

ScheduleAtFixedRate方法:下一次執行時間相對於上一次開始的時間點,因此執行時間一般不會延後,存在併發性。

public class ScheduleFixRateDiff {

    public static void main(String[] args) {
        final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();

        System.out.println("Current time is: " + df.format(calendar.getTime()));

        Timer timer = new Timer();
        /** 第一次執行時間為6秒之前,隨後每隔兩秒執行一次 **/
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                try{
                    /** 任務執行時間3秒 **/
                    Thread.sleep(3000);
                }catch (InterruptedException e){

                }

                /** 列印當前的計劃執行時間 **/
                System.out.println("Scheduled exec time is: " + df.format(scheduledExecutionTime()));
                System.out.println("Task is being executed!");
            }
        }, calendar.getTime(), 2000);

    }
}

這裡寫圖片描述