码迷,mamicode.com
首页 > 其他好文 > 详细

Timer与ScheduledThreadPoolExecutor

时间:2017-11-27 16:46:17      阅读:121      评论:0      收藏:0      [点我收藏+]

标签:scheduledthreadpoole

自JDK1.5开始,JDK提供了ScheduledThreadPoolExecutor类来支持周期性任务的调度。在这之前的实现需要依靠Timer和TimerTask或者其它第三方工具来完成。但Timer有不少的缺陷:

  • Timer是单线程模式;

  • 如果在执行任务期间某个TimerTask耗时较久,那么就会影响其它任务的调度;

  • Timer的任务调度是基于绝对时间的,对系统时间敏感;

  • Timer不会捕获执行TimerTask时所抛出的异常,由于Timer是单线程,所以一旦出现异常,则线程就会终止,其他任务也得不到执行。

ScheduledThreadPoolExecutor继承ThreadPoolExecutor来重用线程池的功能,它的实现方式如下:

  • 将任务封装成ScheduledFutureTask对象,ScheduledFutureTask基于相对时间,不受系统时间的改变所影响;

  • ScheduledFutureTask实现了java.lang.Comparable接口和java.util.concurrent.Delayed接口,所以有两个重要的方法:compareTo和getDelay。compareTo方法用于比较任务之间的优先级关系,如果距离下次执行的时间间隔较短,则优先级高;getDelay方法用于返回距离下次任务执行时间的时间间隔;

  • ScheduledThreadPoolExecutor定义了一个DelayedWorkQueue,它是一个有序队列,会通过每个任务按照距离下次执行时间间隔的大小来排序;

  • ScheduledFutureTask继承自FutureTask,可以通过返回Future对象来获取执行的结果。

通过如上的介绍,可以对比一下Timer和ScheduledThreadPoolExecutor:

TimerScheduledThreadPoolExecutor
单线程多线程
单个任务执行时间影响其他任务调度多线程,不会影响
基于绝对时间基于相对时间
一旦执行任务出现异常不会捕获,其他任务得不到执行多线程,单个任务的执行不会影响其他线程

所以,在JDK1.5之后,应该没什么理由继续使用Timer进行任务调度了。

ScheduledThreadPoolExecutor实现分析:

该线程池与普通的ThreadPoolExecutor类似 就是阻塞队列用了DelayedWorkQueue,这种队列就是利用了最小堆的存储结构对任务进行存放。schedule方法类似submit方法,将任务提交,同时设置delay时间和单位还有周期等,当然这个类也提供submit和execute。放在最小堆顶端的节点是delay最小的任务,也就是每当worker从队列中取出第一个任务都是delay最小的任务,然后查看他的delay值,通过condition.awaitNanos方法阻塞线程到delay时间,等待delay时间后worker才开始执行那个任务。

Timer与ScheduledThreadPoolExecutor

标签:scheduledthreadpoole

原文地址:http://blog.51cto.com/2839840/2044718

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!