最近有同事提出在项目中使用JDK自带的定时器,之前的任务调度一直使用的是Quartz,对Timer没有研究过。因此研究了下如何使用Timer。
- 每一个Timer会启动一个线程(TimerThread),如下代码将产生5个定时器线程
import java.util.Timer; import java.util.TimerTask; public class TimerTestCase { public static void main(String[] args) throws Exception { for (int i = 0; i < 5; i++) { Timer timer = new Timer(); timer.schedule(new MyTask(i), 10000); } } } class MyTask extends TimerTask { private int i; public MyTask(int i){ this.i = i; } @Override public void run() { System.out.println(i); } }
- 每一个Timer可以添加多个TimerTask
import java.util.Timer; import java.util.TimerTask; public class TimerTestCase { public static void main(String[] args) throws Exception { Timer timer = new Timer(); for (int i = 0; i < 5; i++) { timer.schedule(new MyTask(i), 10000); } } } class MyTask extends TimerTask { private int i; public MyTask(int i){ this.i = i; } @Override public void run() { System.out.println(i); } }
- TimerTask会被放入一个有优先级的队列(TimerQueue)中
import java.util.Timer; import java.util.TimerTask; public class TimerTestCase { public static void main(String[] args) throws Exception { Timer timer = new Timer(); for (int i = 0; i < 5; i++) { timer.schedule(new MyTask(i), (10-i)*1000); } } } class MyTask extends TimerTask { private int i; public MyTask(int i){ this.i = i; } @Override public void run() { System.out.println(i); } }
- Timer和TimerTask都是可以被取消的
- 在同一个TimerQueue中,如果前一个TimerTask没有执行完,那么下一个TimerTask是不会被执行的
正常的结果,输出相差1秒import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class TimerTestCase { public static void main(String[] args) throws Exception { Timer timer = new Timer(); for (int i = 0; i < 5; i++) { timer.schedule(new MyTask(i), (10-i)*1000); } } } class MyTask extends TimerTask { private int i; public MyTask(int i){ this.i = i; } @Override public void run() { // try { // Thread.sleep(i * 1000); // } catch (InterruptedException e) { // e.printStackTrace(); // } System.out.println(i + ":" +new Date()); } }
4:Sun Jan 20 22:55:17 CST 2013 3:Sun Jan 20 22:55:18 CST 2013 2:Sun Jan 20 22:55:19 CST 2013 1:Sun Jan 20 22:55:20 CST 2013 0:Sun Jan 20 22:55:21 CST 2013
第一个任务的延迟使之后所有任务都延迟import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class TimerTestCase { public static void main(String[] args) throws Exception { Timer timer = new Timer(); for (int i = 0; i < 5; i++) { timer.schedule(new MyTask(i), (10-i)*1000); } } } class MyTask extends TimerTask { private int i; public MyTask(int i){ this.i = i; } @Override public void run() { try { Thread.sleep(i * 1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i + ":" +new Date()); } }
4:Sun Jan 20 22:57:08 CST 2013 3:Sun Jan 20 22:57:11 CST 2013 2:Sun Jan 20 22:57:13 CST 2013 1:Sun Jan 20 22:57:14 CST 2013 0:Sun Jan 20 22:57:14 CST 2013
- schedule(TimerTask task, Date time):在指定时间执行任务,如果指定的时间比早于当前时间,则马上执行
- schedule(TimerTask task, long delay):延迟delay毫秒之后执行任务
- scheduleAtFixedRate和schedule的区别
结果如下,scheduleAtFixedRate无论在什么情况下都已固定频率执行,而schedule则可能延迟import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class TimerTestCase { public static void main(String[] args) throws Exception { Timer timer = new Timer(); System.out.println(new Date()); timer.schedule(new MyTask(0), 1000, 2000); timer.scheduleAtFixedRate(new MyTask(1), 1000, 2000); } } class MyTask extends TimerTask { private int i; public MyTask(int i){ this.i = i; } @Override public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i + ":" +new Date()); } }
Sun Jan 20 23:06:49 CST 2013 0:Sun Jan 20 23:06:53 CST 2013 1:Sun Jan 20 23:06:56 CST 2013 1:Sun Jan 20 23:06:59 CST 2013 0:Sun Jan 20 23:07:02 CST 2013 1:Sun Jan 20 23:07:05 CST 2013 1:Sun Jan 20 23:07:08 CST 2013 1:Sun Jan 20 23:07:11 CST 2013 1:Sun Jan 20 23:07:14 CST 2013 0:Sun Jan 20 23:07:17 CST 2013
Timer的缺陷:
- Timer是基于绝对时间的,因此任务的执行对系统时间变化很敏感
- 如果TimerTask执行时间过长,会破坏其他TimerTask的定时精确性
- 如果TimerTask抛出一个未受检查的异常,Timer线程并不捕获,线程将被终止,尚未执行的TimerTask将不会再执行
在Java 5.0或者更高的版本中,可以使用ScheduledThreadPoolExecutor代替Timer。