当前位置: 首页 > news >正文

Timer实现定时调度的原理是什么?

Java中的Timer类是一个定时调度器,用于在指定的时间点执行任务。JDK 中Timer类的定义如下:

public class Timer {/*** The timer task queue.  This data structure is shared with the timer* thread.  The timer produces tasks, via its various schedule calls,* and the timer thread consumes, executing timer tasks as appropriate,* and removing them from the queue when they're obsolete.*/private final TaskQueue queue = new TaskQueue();/*** The timer thread.*/private final TimerThread thread = new TimerThread(queue);
}

以上就是Timer中最重要的两个成员变量:

1. TaskQueue:一个任务队列,用于存储已计划的定时任务。任务队列按照任务的执行时间进行排序,确保最早执行的任务排在队列前面。在队列中的任务可能是一次性的,也可能是周期性的。2. TimerThread:Timer 内部的后台线程,它负责扫描 TaskQueue 中的任务,检查任务的执行时间,然后在执行时间到达时执行任务的 run() 方法。

任务的定时调度的核心代码就在TimerThread中:

class TimerThread extends Thread {boolean newTasksMayBeScheduled = true;/*** 存储 TimerTask 的队列*/private TaskQueue queue;TimerThread(TaskQueue queue) {this.queue = queue;}public void run() {try {mainLoop();} finally {synchronized (queue) {newTasksMayBeScheduled = false;queue.clear(); }}}/*** 主要的计时器循环。 */private void mainLoop() {while (true) {try {TimerTask task;boolean taskFired;synchronized (queue) {// 等待队列变为非空while (queue.isEmpty() && newTasksMayBeScheduled)queue.wait();if (queue.isEmpty())break; // 队列为空,将永远保持为空;线程终止// 队列非空;查看第一个事件并执行相应操作long currentTime, executionTime;task = queue.getMin();synchronized (task.lock) {if (task.state == TimerTask.CANCELLED) {queue.removeMin();continue;  // 无需执行任何操作,再次轮询队列}currentTime = System.currentTimeMillis();executionTime = task.nextExecutionTime;if (taskFired = (executionTime <= currentTime)) {if (task.period == 0) { // 非重复,移除queue.removeMin();task.state = TimerTask.EXECUTED;} else { // 重复任务,重新安排queue.rescheduleMin(task.period < 0 ? currentTime   - task.period: executionTime + task.period);}}}if (!taskFired) // 任务尚未触发;等待queue.wait(executionTime - currentTime);}if (taskFired)  // 任务触发;运行它,不持有锁task.run();} catch (InterruptedException e) {}}}
}

可以看到,TimerThread的实际是在运行mainLoop方法,这个方法一进来就是一个while(true)的循环,他在循环中不断地从TaskQueue中取出第一个任务,然后判断他是否到达执行时间了,如果到了,就触发任务执行。否则就继续等一会再次执行。不断地重复这个动作,从队列中取出第一个任务进行判断,执行。。。

这样只要有新的任务加入队列,就在队列中按照时间排序,然后唤醒timerThread重新检查队列进行执行就可以了。代码如下:

private void sched(TimerTask task, long time, long period) {if (time < 0)throw new IllegalArgumentException("Illegal execution time.");// Constrain value of period sufficiently to prevent numeric// overflow while still being effectively infinitely large.if (Math.abs(period) > (Long.MAX_VALUE >> 1))period >>= 1;synchronized(queue) {if (!thread.newTasksMayBeScheduled)throw new IllegalStateException("Timer already cancelled.");synchronized(task.lock) {if (task.state != TimerTask.VIRGIN)throw new IllegalStateException("Task already scheduled or cancelled");task.nextExecutionTime = time;task.period = period;task.state = TimerTask.SCHEDULED;}//新任务入队列queue.add(task);//唤醒任务if (queue.getMin() == task)queue.notify();}}

http://www.lryc.cn/news/609336.html

相关文章:

  • PPT 转高精度 PDF API 接口
  • 使用DrissionPage实现xhs笔记自动翻页并爬取笔记视频、图片
  • Coin Combinations I(Dynamic Programming)
  • Docker环境离线安装指南
  • 解剖 .NET 经典:从 Component 到 BackgroundWorker
  • node.js常用函数
  • GaussDB case when的用法
  • SpringBoot AI自动化测试实战案例
  • GitCode疑难问题诊疗
  • Linux命令基础(下)
  • 1.内核模块
  • 14.Redis 哨兵 Sentinel
  • 2. 字符设备驱动
  • IO流-对象流
  • 克罗均线策略思路
  • `npm error code CERT_HAS_EXPIRED‘ 问题
  • Java Stream API 编程实战
  • 2025年渗透测试面试题总结-2025年HW(护网面试) 77-1(题目+回答)
  • 《测试驱动的React开发:从单元验证到集成协同的深度实践》
  • 【2025ICCV-目标检测方向】WaveMamba:用于 RGB-红外目标检测的小波驱动曼巴融合
  • 百度招黑产溯源安全工程师
  • SQL注入SQLi-LABS 靶场less31-38详细通关攻略
  • Maxscript在选择的可编辑多边形每个面上绘制一个内部圆形
  • 【高等数学】第七章 微分方程——第十节 常系数线性微分方程组解法举例
  • [硬件电路-140]:模拟电路 - 信号处理电路 - 锁定放大器概述、工作原理、常见芯片、管脚定义
  • 类与对象(中),咕咕咕
  • Zama的使命
  • 零确认双花攻击
  • 8月3日星期日今日早报简报微语报早读
  • 《从原理到实践:MySQL索引优化与SQL性能调优全解析》