1. 程式人生 > >Timer和TimerTask定時器使用

Timer和TimerTask定時器使用

Timer是一種定時器工具,用來在一個後臺執行緒計劃執行指定任務。它可以計劃執行一個任務一次或反覆多次。 
TimerTask一個抽象類,它的子類代表一個可以被Timer計劃的任務。具體的任務在TimerTask中run介面中實現。 
通過Timer中的schedule方法啟動定時任務。

一、執行定時器
啟動一個定時器實質是啟動一個執行緒 
1、在指定日期執行定時器任務,只執行一次   

public static void main(String[] args) throws ParseException {
        String sdate = "2018-02-14";
        SimpleDateFormat sf = new SimpleDateFormat("yy-MM-dd");
        Date date = sf.parse(sdate);

        Timer timer = new Timer();
        timer.schedule(new TimerTask() {

            @Override
            public void run() {
                System.out.println("系統正在執行……");
            }
        }, date); //在指定的日期執行一次定時任務
    /*如果date日期在今天之前,則啟動定時器後,立即執行一次定時任務run方法*/
    /*如果date日期在今天之後,則啟動定時器後,會在指定的將來日期執行一次任務run方法*/
    }


2、在距當前時刻的一段時間後執行定時器任務,只執行一次   

public static void main(String[] args) {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {

            @Override
            public void run() {
                System.out.println("系統正在執行……");
            }
        }, 5000); //指定啟動定時器5s之後執行定時器任務run方法,並且只執行一次
    }


3、在指定的時間後,每隔指定的時間,重複執行定時器任務   

public static void main(String[] args) throws ParseException {
        String sdate = "2018-02-10";
        SimpleDateFormat sf = new SimpleDateFormat("yy-MM-dd");
        Date date = sf.parse(sdate);

        Timer timer = new Timer();
        timer.schedule(new TimerTask() {

            @Override
            public void run() {
                System.out.println("系統正在執行……");
            }
        }, date, 2000);
        /*如果指定的date時間是當天或者今天之前,啟動定時器後會立即每隔2s執行一次定時器任務*/
        /*如果指定的date時間是未來的某天,啟動定時器後會在未來的那天開始,每隔2s執行一次定時器任務*/
    }


4、在距當前時刻的一段指定距離後,每隔指定時間執行一次定時器任務   

public static void main(String[] args) {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {

            @Override
            public void run() {
                System.out.println("系統正在執行……");
            }
        }, 5000, 2000);
        /*當啟動定時器後,5s之後開始每隔2s執行一次定時器任務*/
    }


二、停止定時器
停止定時器實質是終止Timer的執行緒。預設情況下,建立的Timer執行緒會一直執行,如果要停止的話主要有以下四種方法終止Timer執行緒:

呼叫Timer的cancel方法;
把Timer執行緒設定成Daemon守護執行緒,當所有的使用者執行緒結束後,那麼守護執行緒也會被終止;
當所有的任務執行結束後,刪除對應Timer物件的引用,執行緒也會被終止;
呼叫System.exit方法終止程式

舉例用cancel方法終止Timer執行緒   

 public static void main(String[] args) throws InterruptedException {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {

            @Override
            public void run() {
                System.out.println("系統正在執行……");
//              timer.cancel(); //可以在任何時刻呼叫cancel方法終止timer執行緒
            }
        }, 5000, 2000);

        /*如果主執行緒不休眠一段時間,就執行了cancel方法,那麼定時器還沒來得及執行就會被關閉*/
        Thread.sleep(6000);
        timer.cancel();
    }


三、啟動任務schedule 與 scheduleAtFixedRate的區別
1、schedule   

 public static void main(String[] args) throws ParseException {
        SimpleDateFormat sf = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
        Date date = sf.parse("2018-02-12 18:33:00");

        Timer timer = new Timer();
        timer.schedule(new TimerTask() {

            @Override
            public void run() {
                System.out.println(new Date() + "系統正在執行……");
            }
        }, date, 10*1000);

    }


執行,輸出如下:

Mon Feb 12 18:35:41 CST 2018系統正在執行……
Mon Feb 12 18:35:51 CST 2018系統正在執行……
Mon Feb 12 18:36:01 CST 2018系統正在執行……
Mon Feb 12 18:36:11 CST 2018系統正在執行……
Mon Feb 12 18:36:21 CST 2018系統正在執行……
Mon Feb 12 18:36:31 CST 2018系統正在執行……
………………………………


如果定時器的起始時間是過去的某個時刻,那麼當啟動定時器後,會從當前時刻開始算,每隔10s執行一次定時器任務。指定的起始時間是2018-02-12 18:33:00 ,而當前時間是18:35:41 ,因此從18:35:41 時刻開始每隔10s執行一次定時器任務。

2、scheduleAtFixedRate   

public static void main(String[] args) throws ParseException {
        SimpleDateFormat sf = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
        Date date = sf.parse("2018-02-12 18:39:00");

        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {

            @Override
            public void run() {
                System.out.println(new Date() + "系統正在執行……");
            }
        }, date, 10*1000);
    }


執行定時器方法,輸出結果如下:

Mon Feb 12 18:42:10 CST 2018系統正在執行……
Mon Feb 12 18:42:10 CST 2018系統正在執行……
Mon Feb 12 18:42:10 CST 2018系統正在執行……
Mon Feb 12 18:42:10 CST 2018系統正在執行……
Mon Feb 12 18:42:10 CST 2018系統正在執行……
Mon Feb 12 18:42:10 CST 2018系統正在執行……
Mon Feb 12 18:42:10 CST 2018系統正在執行……
Mon Feb 12 18:42:10 CST 2018系統正在執行……
Mon Feb 12 18:42:10 CST 2018系統正在執行……
Mon Feb 12 18:42:10 CST 2018系統正在執行……
Mon Feb 12 18:42:10 CST 2018系統正在執行……
Mon Feb 12 18:42:10 CST 2018系統正在執行……
Mon Feb 12 18:42:10 CST 2018系統正在執行……
Mon Feb 12 18:42:10 CST 2018系統正在執行……
Mon Feb 12 18:42:10 CST 2018系統正在執行……
Mon Feb 12 18:42:10 CST 2018系統正在執行……
Mon Feb 12 18:42:10 CST 2018系統正在執行……
Mon Feb 12 18:42:10 CST 2018系統正在執行……
Mon Feb 12 18:42:10 CST 2018系統正在執行……
Mon Feb 12 18:42:10 CST 2018系統正在執行……
Mon Feb 12 18:42:20 CST 2018系統正在執行……
Mon Feb 12 18:42:30 CST 2018系統正在執行……


如果指定的起始時間是過去某個時刻,定時器會迅速執行完從起始時刻到當前時刻要執行的定時器任務次數,然後再每隔10s執行一次定時器任務。 
網上有段解釋: 
對於scheduleAtFixedRate,如果指定開始時間是2005/12/30 14:10:00,間隔為3分鐘,如果在14:17:00分執行這個程式,會立刻執行3次定時器任務,分別對應14:10:00、14:13:00、14:16:00 時刻應該執行的定時任務,那麼第四次執行定時器任務的時間應該是14:19:00,而不是14:20:00 ,就是說是從指定的開始時間開始計時,而不是從執行時間開始計時。 
但是如果用schedule,間隔時間是3分鐘,指定開始時間是2005/12/30 14:10:00,那麼在14:17:00分執行這個程式,則立即執行程式一次。並且下一次的執行時間是 14:20,而不是從14:10開始算的週期(14:19)。

四、啟動定時器原始碼
啟動一個定時器實質是啟動一個執行緒,每建立一個定時器,就需要新建一個執行緒,用新建立的執行緒去執行定時器任務。 
當執行Timer timer = new Timer(); 時,執行了Timer的無參構造器

   

public Timer() {
        this("Timer-" + serialNumber());
    }


然後呼叫了Timer的有參構造器,設定執行緒的名字,然後啟動執行緒

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


原文:https://blog.csdn.net/u010502101/article/details/79318380