Timer是用於管理在后台執行的延遲任務或周期性任務,其中的任務使用java.util.TimerTask表示。任務的執行方式有兩種:
按固定速率執行:即scheduleAtFixedRate的兩個重載方法
按固定延遲執行:即schedule的4個重載方法
具體差別會在后面詳細說明。
我們要實現一個定時任務,只需要實現TimerTask的run方法即可。每一個任務都有下一次執行時間nextExecutionTime(毫秒),如果是周期性的任務,那么每次執行都會更新這個時間為下一次的執行時間,當nextExecutionTime小於當前時間時,都會執行它。
一、使用方式
Timer的具體使用方法非常簡單,比如:
Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { System.out.println("Timer is running"); } }, 2000);
上面這個定時任務表示在2秒后開始執行,只執行一次。當然還可以執行周期性任務,只需要添加schedule的第三個參數period,如:
Timer timer = new Timer(); timer. scheduleAtFixedRate(new TimerTask() { @Override public void run() { System.out.println("Timer is running"); } }, 2000, 5000);
表示2秒后開始執行,然后每隔5秒執行一次。
二、Timer的缺陷
1、由於執行任務的線程只有一個,所以如果某個任務的執行時間過長,那么將破壞其他任務的定時精確性。如一個任務每1秒執行一次,而另一個任務執行一次需要5秒,那么如果是固定速率的任務,那么會在5秒這個任務執行完成后連續執行5次,而固定延遲的任務將丟失4次執行。
2、如果執行某個任務過程中拋出了異常,那么執行線程將會終止,導致Timer中的其他任務也不能再執行。
3、Timer使用的是絕對時間,即是某個時間點,所以它執行依賴系統的時間,如果系統時間修改了的話,將導致任務可能不會被執行。
三、更好的替代方法
由於Timer存在上面說的這些缺陷,在JDK1.5中,我們可以使用ScheduledThreadPoolExecutor來代替它,使用Executors.newScheduledThreadPool工廠方法或使用ScheduledThreadPoolExecutor的構造函數來創建定時任務,它是基於線程池的實現,不會存在Timer存在的上述問題,當線程數量為1時,它相當於Timer。