深入 Java Timer 定时任务调度器实现原理

  • 时间:
  • 浏览:0

任意多tcp连接 都才能通过 Timer.schedule 辦法 将任务加入 TaskQueue,若果 TaskQueue 又并才能多tcp连接 安全的数据行态。所在每次修改 TaskQueue 时都才能加锁。

当 Timer 被回收时,内控 字段 threadPeaper 指向的对象也会被回收。可是我 finalize 辦法 原应被调用,唤醒并终止 Timer 轮训多tcp连接 。原应才还可不能否 這個 threadPeaper 对象就原应会原应 JVM 里留下僵尸多tcp连接 。

原文发布时间为:2018-12-17

本文作者:老钱

本文来自云栖社区企业相互合作伙伴“ [码洞](https://mp.weixin.qq.com/s/4FfzHb4O3fWE3XbiGCx8QQ

)”,了解相关信息才能关注“codehole”微信公众号

对于固定传输效率来说,原应任务执行时间太长超出了间隔,才还可不能否 它原应会持续霸占任务队列,原应它的调度时间将老要低于 currentTime,排在堆顶,每次轮训取出来的才能它。运行完毕后,重新调度這個任务,它的时间依旧赶不上。持续下去让人看后這個任务的调度时间远远落后于当前时间,而其它任务原应会彻底饿死。这可是我为哪些地方一定要怪怪的注意固定传输效率的循环任务运行时间不宜过长。

Timer 的任务队列 TaskQueue 是有有有两个 特殊的队列,它内控 是有有有两个 数组。這個数组会按照待执行时间进行堆排序,堆顶元素老要待执行时间最小的任务。轮训多tcp连接 会每次轮训出时间点最近的若果到点的任务来执行。数组会自动扩容,原应任务非常多。

对于有有有两个 循环任务来说,它不地处 EXECUTED 请况,原应它每次还会执行完成,就被重新调度了。EXECUTED 请况仅仅地处于一次性任务,若果這個请况随便说说并才能表示任务原应执行完成,它是指原应从任务队列里摘出来了,马上就要执行。

内控 行态

Timer 类里包蕴暗包含两个 任务队列和有有有两个 异步轮训多tcp连接 。任务队列里容纳了所有待执行的任务,所有的任务原应在这有有有两个 异步多tcp连接 里执行,切记任务的执行代码不才能抛出异常,若果会原应 Timer 多tcp连接 挂掉,所有的任务都都这样执行了。单个任务可是我易执行时间太长,若果会影响任务调度在时间上的精准性。比如你有有有两个 任务跑了不多,其它等着调度的任务就老要地处饥饿请况得才能 调度。所有任务的执行才能这单一的 TimerThread 多tcp连接 。

亲们还注意到 Timer.cancel() 辦法 会唤醒轮训多tcp连接 ,为的是才能立即停止轮训。不过原应任务正在执行中,这还会 cancel() 就才能等到任务执行完毕才才能停止。

任务队列空了

任务队列才能才能 任务了,调度多tcp连接 才能按一定的策略进行睡眠。它才能睡眠老要到最先执行的任务到点时立即醒来,可是我睡眠截止时间可是我第有有有两个 任务将要执行的时间。一起去在睡觉的还会,有原应会有新的任务被添添加来,它的调度时间原应会更加提前,可是我当有新的任务到来时才能才能唤醒正在睡眠的多tcp连接 。

任务锁

Timer 的任务支持退还操作,退还任务的多tcp连接 和执行任务的多tcp连接 极有原应才能有有有两个 多tcp连接 。有原应任务正在执行中,结果另有有两个 多tcp连接 表示要退还任务。这还会 Timer 是如可防止的呢?在 TimerTask 类里看后了一把锁。当任务属性才能修改的还会,才能加锁。

任务请况

TimerTask 有 4 个请况,VIRGIN 是默认请况,还会实例化还才还可不能否 被调度。SCHEDULED 表示原应将任务装入去 TaskQueue 等待英文被执行。EXECUTED 表示任务原应执行完成。CANCELLED 表示任务被退还了,还没来得及执行就被人为退还了。

Timer 终止

Timer 提供了 cancel() 辦法 清空队列,停止调度器,不允许有任何新任务进来。它会将 newTasksMayBeScheduled 字段设置为 false 表示 Timer 即将终止。

在任务运行过才能检查任务是才能原应被退还了,原应退还了,就从队列中移除。一旦任务结速了了运行 run(),对于单次任务来说它就无法被退还了,而循环任务将不需要继续下次调度。原应任务才还可不能否 原应得到执行(时间设置的太长),才还可不能否 即使這個任务被退还了,它也会老要持续躺在任务队列中。设想原应你调度了一系列久远的任务,若果都退还了,这原应会成为有有有两个 内存泄露点。可是我 Timer 还单独提供了有有有两个 purge() 辦法 才能一次性清空所有的已退还的任务。

原应 Timer 终止了,还有新任务进来就会抛出异常。

代码中的 wait() 辦法 可是我调用了 Object.wait() 来进行睡眠。当有新任务进来了,发现這個新任务的运行时间是最早的,那就调用 notify() 辦法 唤醒轮训多tcp连接 。

任务间隔字段 period 比较特殊,当使用固定传输效率时,period 为正值,当使用固定间隔时,period 为负值,当任务是一次性时,period 为零。下面是循环任务的下次调度时间设定

使用 Java 来调度定时任务时,亲们老要会使用 Timer 类搞定。Timer 简单易用,其源码阅读起来也非常清晰,本节亲们来仔细分析一下 Timer 类,来看看 JDK 源码的编写者是如可实现有有有两个 稳定可靠的简单调度器。

Timer 使用

Timer 调度任务有一次性调度和循环调度,循环调度有分为固定传输效率调度(fixRate)和固定传输效率调度(fixDelay)。固定传输效率就好比你今天加班到很晚,若果到了第三三十天还才能准点到公司上班,原应你一不小心加班到了第三三十天早上 9 点,你就连休息的时间都才还可不能否 了。而固定传输效率的意思你都这样才能睡够 8 个小时再过来上班,原应你加班到午夜 6 点,那就才能下午过来上班了。固定传输效率强调准点,固定传输效率强调间隔。

垃圾回收

还有有有有两个 特殊的场景才能怪怪的注意,那可是我当轮训多tcp连接 原应队列才能才能 任务而睡眠的还会,Timer 对象原应不再被引用而被垃圾回收了。这还会才能主动唤醒轮训多tcp连接 ,让它退出。

原应你有有有有两个 任务才能每天准点调度,那就应该使用固定传输效率调度,若果要确保每个任务执行时间何必 太长,千万别超过了第三三十天這個点。原应你有有有有两个 任务才能每隔几分钟跑一次,那就使用固定传输效率调度,它才能很在乎你的单个任务要跑多长时间。