今天闲来无事读Java中Timer的源码,发现Timer的注释中有这么一段
其大意是说Timer的API有单线程的问题,一个定时器不允许同时执行任务。官方说在JDK1.5之后引入了ScheduledThreadPoolExecutor类来实现多线程的定时器。那就来看看到底是怎么回事把。
Timer
- 通过日志不难看出,在一个Timer中的2个TimerTask是有执行顺序的,也就是上一个没有执行完,下一个是不会触发的。而究其原因,看源码发现Timer的实现中只有一个TimerThread线程通过
while (true)
的loop来执行存储在TaskQueue中的定时器任务
- 并且在loop的过程中只捕获了InterruptedException导致其中一个Task出现错误,会影响接下来的所有Task的执行。
- 打开TimerTest中注释掉的
throw new RuntimeException("Exception occured here!");
代码,会发现Task2不会执行。
ScheduledThreadPoolExecutor
- 观察到的结果如下,可以发现是跟Timer的执行结果是一样的
- 此时,修改
Executors.newScheduledThreadPool(1)
为Executors.newScheduledThreadPool(2)
创建两个线程来执行定时器任务,观察到结果预期应该是每秒钟2个任务同时执行,结果如下,符合预期
- 当打开
throw new RuntimeException("Exception occured here!");
之后会发现Schedule2正常执行,Schedule1的异常不会影响Schedule2的执行
结论
Timer可以做的事情,通过ScheduledThreadPoolExecutor都可以做到,并且修复了其中Timer的部分设计上的缺陷。并且实现了多线程的执行,相对来说功能是比Timer强大了一个等级。
参考资料:
Java 并发专题:Timer的缺陷 用ScheduledExecutorService替代 : http://blog.csdn.net/lmj623565791/article/details/27109467