惠州网站关键词排名,汕头seo外包,琼海市规划建设局网站,中国菲律宾最新消息Java中Timer实现定时调度的原理 ✔️ 引言✔️JDK 中Timer类的定义✔️拓展知识仓✔️优缺点 ✔️ 引言 Java中的Timer类是用于计划执行一项任务一次或重复固定延迟执行的简单工具。它使用一个名为TaskQueue的内部类来存储要执行的任务#xff0c;这些任务被封装为TimerTask对… Java中Timer实现定时调度的原理 ✔️ 引言✔️JDK 中Timer类的定义✔️拓展知识仓✔️优缺点 ✔️ 引言 Java中的Timer类是用于计划执行一项任务一次或重复固定延迟执行的简单工具。它使用一个名为TaskQueue的内部类来存储要执行的任务这些任务被封装为TimerTask对象。 Timer实现定时调度的基本原理
创建 Timer 对象当你创建一个Timer对象时它会实例化一个线程不是守护线程这个线程用于执行计划任务。添加任务你可以使用schedule或scheduleAtFixedRate方法向Timer添加任务。这些方法接受一个TimerTask对象和一个延迟时间以及可选的重复间隔。内部存储Timer内部使用一个优先级队列具体是TaskQueue类来存储要执行的任务。队列中的每个元素都是一个表示要执行的任务的TimerTask对象。队列根据任务的执行时间进行排序以确保任务按照预定的时间顺序执行。执行线程Timer类的线程在后台运行并定期检查任务队列。当线程发现队列中有任务到达其预定的执行时间时它会从队列中取出该任务并执行它。处理重复任务对于需要重复执行的任务Timer会重新计算下一个执行时间并将任务重新放入队列中。这样当任务的下一次执行时间到达时线程会再次从队列中取出并执行它。取消任务你可以使用Timer.cancel()方法来取消所有已调度的任务或者使用TimerTask.cancel()方法来取消单个任务。取消的任务将从队列中移除并且不会再次调度。注意事项虽然Timer在简单场景下可以很好地工作但它并不是最适合所有场景的定时任务解决方案。特别是在需要更复杂的调度需求或在并发环境中使用ScheduledExecutorService可能是更好的选择。
总而言之Java中的Timer类通过内部使用一个优先级队列来存储和管理定时任务并通过一个单独的线程来检查和执行这些任务从而实现了定时调度功能。 ✔️JDK 中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 theyre obsolete.*/private final TaskOueue queue new TaskOueue() ;/*** The timer thread*/private final TimerThread thread new TimerThread(queue);
}以上就是 Timer 中最重要的两入成员变量 1、TaskQueue: 一个任务队列用于存储已计划的定时任务。任务队列按照任务的执行时间进行排序确保最早执行的任务排在队列前面。在队列中的任务可能是一次性的也可能是周期性的。 2、TimerThread : Timer 内部的后台线程它负责扫描 TaskQueue 中的任务检查任务的执行时间然后在执行时间到达时执行任务的 run() 方法。TimerThread 是一个守护线程因此当所有非守护线程完成时它会随之终止。 任务的定时调度的核心代码就在TimerThread 中 /**
* author xinbaobaba
*/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 ? 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();}
}✔️拓展知识仓 ✔️优缺点 Timer 类用于实现定时任务最大的好处就是他的实现非常简单特别的轻量级因为它是Java内置的所以只需要简单调用就行了。 但是他并不是特别好的解决定时任务的方案因为他存在以下问题 1、Timer内部是单线程执行任务的如果某个任务执行时间较长会影响后续任务的执行 2、如果任务抛出未捕获异常将导致整个 Timer 线程终止影响其他任务的执行 3、Timer 无法提供高精度的定时任务。因为系统调度和任务执行时间的不确定性可能导致任务执行的时间不准确 4、虽然可以使用 cancel 方法取消任务但这仅仅是将任务标记为取消状态仍然会在任务队列中占用位置无法释放资源。这可能导致内存泄漏 5、当有大量任务时Timer 的性能可能受到影响因为它在每次扫描任务队列时都要进行时间比较 6、Timer执行任务完全基于JVM内存一旦应用重启那么队列中的任务就都没有了