原創文章,如需轉載,請註明出處。
關於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) |