【高并发】ScheduledThreadPoolExecutor 与 Timer 的区别和简单示例
JDK 1.5 开始提供 ScheduledThreadPoolExecutor 类,ScheduledThreadPoolExecutor 类继承 ThreadPoolExecutor 类重用线程池实现了任务的周期性调度功能。在 JDK 1.5 之前,实现任务的周期性调度主要使用的是 Timer 类和 TimerTask 类。本文,就简单介绍下 ScheduledThreadPoolExecutor 类与 Timer 类的区别,ScheduledThreadPoolExecutor 类相比于 Timer 类来说,究竟有哪些优势,以及二者分别实现任务调度的简单示例。
二者的区别
线程角度
Timer 是单线程模式,如果某个 TimerTask 任务的执行时间比较久,会影响到其他任务的调度执行。
ScheduledThreadPoolExecutor 是多线程模式,并且重用线程池,某个 ScheduledFutureTask 任务执行的时间比较久,不会影响到其他任务的调度执行。
系统时间敏感度
Timer 调度是基于操作系统的绝对时间的,对操作系统的时间敏感,一旦操作系统的时间改变,则 Timer 的调度不再精确。
ScheduledThreadPoolExecutor 调度是基于相对时间的,不受操作系统时间改变的影响。
是否捕获异常
Timer 不会捕获 TimerTask 抛出的异常,加上 Timer 又是单线程的。一旦某个调度任务出现异常,则整个线程就会终止,其他需要调度的任务也不再执行。
ScheduledThreadPoolExecutor 基于线程池来实现调度功能,某个任务抛出异常后,其他任务仍能正常执行。
任务是否具备优先级
Timer 中执行的 TimerTask 任务整体上没有优先级的概念,只是按照系统的绝对时间来执行任务。
ScheduledThreadPoolExecutor 中执行的 ScheduledFutureTask 类实现了 java.lang.Comparable 接口和 java.util.concurrent.Delayed 接口,这也就说明了 ScheduledFutureTask 类中实现了两个非常重要的方法,一个是 java.lang.Comparable 接口的 compareTo 方法,一个是 java.util.concurrent.Delayed 接口的 getDelay 方法。在 ScheduledFutureTask 类中 compareTo 方法方法实现了任务的比较,距离下次执行的时间间隔短的任务会排在前面,也就是说,距离下次执行的时间间隔短的任务的优先级比较高。而 getDelay 方法则能够返回距离下次任务执行的时间间隔。
是否支持对任务排序
Timer 不支持对任务的排序。
ScheduledThreadPoolExecutor 类中定义了一个静态内部类 DelayedWorkQueue,DelayedWorkQueue 类本质上是一个有序队列,为需要调度的每个任务按照距离下次执行时间间隔的大小来排序
能否获取返回的结果
Timer 中执行的 TimerTask 类只是实现了 java.lang.Runnable 接口,无法从 TimerTask 中获取返回的结果。
ScheduledThreadPoolExecutor 中执行的 ScheduledFutureTask 类继承了 FutureTask 类,能够通过 Future 来获取返回的结果。
通过以上对 ScheduledThreadPoolExecutor 类和 Timer 类的分析对比,相信在 JDK 1.5 之后,就没有使用 Timer 来实现定时任务调度的必要了。
二者简单的示例
这里,给出使用 Timer 和 ScheduledThreadPoolExecutor 实现定时调度的简单示例,为了简便,我这里就直接使用匿名内部类的形式来提交任务。
Timer 类简单示例
源代码示例如下所示。
运行结果如下所示。
ScheduledThreadPoolExecutor 类简单示例
源代码示例如下所示。
运行结果如下所示。
注意:关于 Timer 和 ScheduledThreadPoolExecutor 还有其他的使用方法,这里,我就简单列出以上两个使用示例,更多的使用方法大家可以自行实现。
版权声明: 本文为 InfoQ 作者【冰河】的原创文章。
原文链接:【http://xie.infoq.cn/article/b5c0ec7aaa480d0d0c26ea9c0】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论