關於Timer的幾個問題

 原創文章,如需轉載,請註明出處。

關於Timer的幾個問題。 Java5.0以後版本,推薦使用ScheduledThreadPoolExecutor替代Timer

 

1.Timer對任務的調度依賴於系統時間

如下示例,如果把系統時間改爲“2010-10-01 00:00:00”,那麼運行代碼,任務會立即執行。

 

示例代碼:

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.Timer;

import java.util.TimerTask;

 

public class OutOfTime {

    public static void main(String[] args) throws Exception {

        Timer timer = new Timer();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

        Date date= sdf.parse("2010-10-01 00:00:00");

        System.out.println(date);

        timer.schedule(new Task("task"), date);

       

    }

 

    static class Task extends TimerTask {

        private String name;

        public Task(String name){

            this.name=name;

        }

        public void run() {

            System.out.println(name);

        }

    }

}

 

2.Timer單線程執行任務,任務有可能丟失或執行時間不準確。

Timer執行任務時只是創建了單個線程。如果一個時間任務執行的時間比較長,那麼其他任務執行時間的準確性就會受影響。比如每隔1秒執行一次短任務,中間有個長任務在當前時間延遲1秒後執行,執行時間超過5秒,那麼短任務就有可能丟失或者在5秒後連續快速的執行而非每隔1秒。

 

示例代碼:

import java.util.Date;

import java.util.Timer;

import java.util.TimerTask;

import static java.util.concurrent.TimeUnit.SECONDS;

 

public class OutOfTime {

    public static void main(String[] args) throws Exception {

        Timer timer = new Timer();

        Date date = new Date();    

        timer.scheduleAtFixedRate(new ShortTask("ShortTask"+1), date,1000);

        timer.schedule(new LongTask("LongTask"+2), 1000);

    }

 

    static class ShortTask extends TimerTask {

        private String name;

        public ShortTask(String name){

            this.name=name;

        }

        public void run() {

            System.out.println(name);

        }

    }

   

    static class LongTask extends TimerTask {

        private String name;

        public LongTask(String name){

            this.name=name;

        }

        public void run() {

            try {

                SECONDS.sleep(5);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

            System.out.println(name);

        }

    }

}

 

3.Timer的線程泄漏問題。

如果TimerTask拋出未檢查的異常,Timer將產生無法預料的行爲。Timer線程並不捕獲異常,所以,TimerTask拋出未檢查的異常會終止Timer線程。在這種情況下,Timer也不會恢復線程,而是錯誤地認爲整個Timer線程被取消了。這時,已經在計劃中但是還沒有執行的TimerTask就再也不會運行了,新的任務也不會被安排了。  

 

示例代碼:

import java.util.Timer;

import java.util.TimerTask;

import static java.util.concurrent.TimeUnit.SECONDS;

 

public class OutOfTime {

    public static void main(String[] args) throws Exception {

        Timer timer = new Timer();

        timer.schedule(new ThrowTask(), 1);

        SECONDS.sleep(1);

        timer.schedule(new ThrowTask(), 1);

        SECONDS.sleep(5);

    }

 

    static class ThrowTask extends TimerTask {

        public void run() {

            throw new RuntimeException();      

        }

    }

}

 

 

拋出的異常:

Exception in thread "Timer-0" java.lang.RuntimeException

    at com.timer.test.OutOfTime$ThrowTask.run(OutOfTime.java:18)

    at java.util.TimerThread.mainLoop(Unknown Source)

    at java.util.TimerThread.run(Unknown Source)

Exception in thread "main" java.lang.IllegalStateException: Timer already cancelled.

    at java.util.Timer.sched(Unknown Source)

    at java.util.Timer.schedule(Unknown Source)

    at com.timer.test.OutOfTime.main(OutOfTime.java:12)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章