天天看點

Android中使用Timer和TimerTask前言簡介使用兩種排程方法的差別

前言

近期有個需求,要每隔一段時間,應用向背景發送一些資料,用作統計,這時可以使用Java提供的計時器的工具類,即Timer和TimerTask來實作這一功能。

簡介

Timer是一個普通的類,其中有幾個重要的方法;而TimerTask則是一個抽象類,其中有一個抽象方法run(),類似線程中的run()方法,我們使用Timer建立一個他的對象,然後調用schedule方法來完成這種間隔的操作。

這裡用到的這個schedule方法有三個參數:

第一個參數就是TimerTask對象,我們實作TimerTask的run()方法就是要周期執行的一個任務;

第二個參數是延遲執行的時間,有兩種類型,第一種是long類型,表示多長時間後開始執行,也就是說使用者調用 schedule() 方法後,要等待這麼長的時間才可以第一次執行run() 方法。另一種是Date類型,表示從那個時間後開始執行;

第三個參數就是執行的周期,為long類型,也就是說第一次調用之後,從第二次開始每隔多長的時間調用一次 run() 方法。

schedule方法還有一種兩個參數的執行重載,第一個參數仍然是TimerTask,第二個表示為long的形式表示多長時間後執行一次,為Date就表示某個時間後執行一次。

Java API:

//Schedules thespecified task for execution after the specifieddelay
schedule(TimerTask task, long delay)//在延時delay毫秒後執行task。并沒有提到重複執行

//Schedulesthe specified task for repeated fixed-delay execution, beginningafter the specified delay
schedule(TimerTask task, long delay, long period)//在延時delay毫秒後重複的執行task,周期是period毫秒。
           

Timer就是一個線程,使用schedule方法完成對TimerTask的排程,多個TimerTask可以共用一個Timer,也就是說Timer對象調用一次schedule方法就是建立了一個線程,并且調用一次schedule後TimerTask是無限制的循環下去的,使用Timer的cancel()停止操作。當然同一個Timer執行一次cancel()方法後,所有Timer線程都被終止。

另外Timer類還有一個排程方法scheduleAtFixedRate(),這個方法的參數與schedule()相同,具體的差別在下邊再說!

使用

//true 說明這個timer以daemon方式運作(優先級低,程式結束timer也自動結束)   
Timer timer = new Timer(true);  

TimerTask task = new TimerTask() {  
   public void run() {  
   //每次需要執行的代碼放到這裡面。     
   }     
};  

//以下是幾種排程task的方法:  

//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()不會将過去的時間計算在内

SimpleDateFormat fTime = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date d1 = fTime.parse("2016/11/08 17:10:00");
timer.schedule(new TimerTask(){
    public void run(){
        System.out.println("this is task running");
    }
},d1,**);
           

如果是在2016/11/08 17:20執行程式,則會在2016/11/08 17:23輸出第一條:this is task running

scheduleAtFixedRate()會将過去的時間計算在内

SimpleDateFormat fTime = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date d1 = fTime.parse("2016/11/08 17:10:00");
timer.scheduleAtFixedRate(new TimerTask(){
    public void run(){
        System.out.println("this is task running");
    }
},d1,**);
           

如果是在2016/11/08 17:20執行程式,則會快速輸出三條:this is task running,第四條将會在2016/11/08 17:22輸出,而不是 17:23!就是說是從指定的開始時間開始計時,而不是從執行時間開始計時。

②任務延遲時的處理不同

schedule如果由于任何原因(如垃圾回收或其他背景活動)而延遲了某次執行,則後續執行也将被延遲。

schedule适用于那些需要“平穩”運作的重複活動。如以固定時間間隔閃爍的光标。

scheduleAtFixedRate如果由于任何原因(如垃圾回收或其他背景活動)而延遲了某次執行,則将快速連續地出現兩次或更多的執行,進而使後續執行能夠“追趕上來”。

scheduleAtFixedRate适用于那些對絕對時間敏感的重複執行活動,如每小時準點打鐘報時,或者在每天的特定時間運作已安排的維護活動。

題外話:

JDK 5.0以後推薦使用ScheduledThreadPoolExecutor,該類屬于Executor Framework,它除了能處理異常外,還可以建立多個線程解決上面的問題。

參考文章:

Java中的Timer和TimerTask在Android中的用法

Timer 的 schedule()方法

Timer類的schedule和scheduleAtFixedRate 簡單應用