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

定时器详解

一、定时器概述

什么是定时器?

Java定时器(Timer)是一种用于在​​指定时间​​或​​周期性间隔​​执行任务的工具,适用于定时任务调度、轮询检测、延迟操作等场景。它通过后台线程实现对任务的自动化调度管理。

定时器也是软件开发中的一个重要组件. 类似于一个 "闹钟". 达到一个设定的时间之后, 就执行某个指定 好的代码. 

核心类与接口

  • java.util.Timer
    单线程任务调度器,通过 schedule() 方法安排任务。
  • java.util.TimerTask
    抽象类,需实现 run() 方法定义具体任务逻辑。
  • ScheduledExecutorService
    更现代的替代方案(Java 5+),基于线程池,提供更灵活的调度控制

二、Java标准库中的Timer类

Timer类核心机制

Java标准库中的java.util.Timer类用于实现定时任务调度,其核心特点是​​单线程任务队列管理​​。所有通过schedule方法提交的任务都会进入同一个线程的任务队列,按预定时间顺序执行。

 schedule方法

方法签名说明

// 单次执行
void schedule(TimerTask task, long delay)// 固定间隔周期性执行(基于前次执行结束时间)
void schedule(TimerTask task, long delay, long period)// 固定速率周期性执行(基于首次执行开始时间)
void scheduleAtFixedRate(TimerTask task, long delay, long period)

参数详解 

参数类型说明
taskTimerTask具体任务对象,需继承并实现run()方法
delaylong首次执行延迟时间(单位:毫秒)
periodlong周期性任务间隔时间(仅限多次执行任务,单位:毫秒)

 使用示例

基础单次任务

Timer timer = new Timer();
timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("延迟2秒执行: " + new Date());}
}, 2000);  // 2000毫秒后执行

周期性任务(固定间隔)

timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("每隔3秒执行: " + new Date());try {Thread.sleep(1000);  // 模拟任务耗时} catch (InterruptedException e) {e.printStackTrace();}}
}, 0, 3000);  // 立即开始,每次间隔3秒(基于任务结束时间)

周期性任务(固定速率)

timer.scheduleAtFixedRate(new TimerTask() {@Overridepublic void run() {System.out.println("固定速率执行: " + new Date());}
}, 0, 3000);  // 立即开始,严格每3秒执行一次

关键注意事项

任务对象要求

  • 必须继承TimerTask抽象类
  • 需要重写run()方法(无返回值)
  • 推荐任务执行时间短于间隔周期

执行特性对比

执行模式特点
单次执行执行后自动从队列移除
schedule()周期性任务间隔基于前次任务结束时间计算
scheduleAtFixedRate()严格按初始时间计划执行,适合需要累积补偿的场景

 阻塞风险示例

Timer timer = new Timer();
timer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("开始长时间任务: " + new Date());try {Thread.sleep(5000);  // 任务耗时超过间隔时间} catch (InterruptedException e) {e.printStackTrace();}}
}, 0, 2000);  // 预期每2秒执行,实际间隔变为5秒以上

三、实现定时器

// 定时任务调度框架核心类/*** 定时任务实体类,实现Comparable接口用于优先级队列排序*/
class Tier implements Comparable<Tier> {private Runnable command;  // 待执行的任务private long time;         // 任务执行时间戳(毫秒)/*** 任务构造函数* @param command 待执行的任务逻辑* @param after 延迟执行时间(毫秒)*/public Tier(Runnable command, long after) {this.command = command;this.time = System.currentTimeMillis() + after;  // 计算绝对执行时间}/*** 任务执行方法*/@Overridepublic void run() {command.run();}/*** 比较器实现(按执行时间排序)*/@Overridepublic int compareTo(Tier o) {return Long.compare(this.time, o.time);  // 时间早的任务优先执行}
}/*** 工作线程类,负责从队列获取并执行任务*/
class Worker extends Thread {private PriorityQueue<Tier> queue = new PriorityQueue<>();  // 优先级任务队列/*** 线程运行主逻辑*/@Overridepublic void run() {while (true) {try {synchronized (queue) {// 队列为空时等待while (queue.isEmpty()) {queue.wait();}// 获取队首任务Tier task = queue.peek();long current = System.currentTimeMillis();long remain = task.time - current;// 未到执行时间时继续等待if (remain > 0) {queue.wait(remain);} else {// 取出并执行任务task = queue.poll();task.run();}}} catch (InterruptedException e) {// 处理线程中断break;  }}}/*** 添加新任务到队列*/public void schedule(Runnable command, long after) {synchronized (queue) {queue.offer(new Tier(command, after));queue.notify();  // 唤醒等待线程}}
}/*** 定时器主类*/
public class Timer {private Worker worker;  // 工作线程实例public Timer() {worker = new Worker();worker.start();  // 启动工作线程}/*** 调度任务方法* @param command 任务逻辑* @param after 延迟时间(毫秒)*/public void schedule(Runnable command, long after) {worker.schedule(command, after);}/*** 示例使用*/public static void main(String[] args) {Timer timer = new Timer();// 调度延迟任务(2000ms后执行)timer.schedule(() -> System.out.println("Task 1 executed"), 2000);// 调度周期性任务(首次延迟1000ms,之后间隔3000ms)timer.schedule(new Runnable() {@Overridepublic void run() {System.out.println("Periodic task executed");// 重新调度实现周期性timer.schedule(this, 3000);  }}, 1000);}
}
  1. 核心设计思想​
    通过优先级队列实现时间排序,Worker线程智能等待,同时使用wait/notify机制优化资源使用

  2. ​线程安全处理​
    在队列操作时使用synchronized同步块,确保多线程环境下的数据一致性

  3. ​延迟计算优化​
    long remain = task.time - current;
    精确计算剩余等待时间,避免无效轮询

  4. ​周期性任务实现技巧​
    在任务内部重新调用schedule方法,形成循环调度链

  5. ​中断处理机制​
    catch代码块中处理InterruptedException,保证线程可被正常终止

四、总结

Java定时器是任务调度的核心工具,理解其原理与差异至关重要。对于简单需求,Timer足够便捷;高并发或复杂调度场景建议采用ScheduledExecutorService。此外,第三方库如Quartz、Spring Task提供了更强大的分布式调度能力,可根据项目需求扩展。

 

相关文章:

  • el-select组件相关总结
  • 一、UI自动化测试01--认识和元素定位方法
  • 如何在学习通快速输入答案(网页版),其他学习平台通用,手机上快速粘贴
  • Redis为什么不直接使用C语言中的字符串?
  • 在应用运维过程中,业务数据修改的证据留存和数据留存
  • Spring Boot 参考文档导航手册
  • BT169-ASEMI无人机专用功率器件BT169
  • JVM运行机制全景图:从源码到执行的全过程
  • 记录前端vue3封装一个modal弹框
  • swagger快速入门
  • css word
  • 微信小程序 - 获取当前地址经纬度
  • 解释PyTorch中的广播机制
  • 使用命令关闭Redis服务端
  • 微信小程序核心技术栈
  • 【前后端分离项目】Vue+Springboot+MySQL
  • k8s中资源的介绍及标准资源namespaces实践
  • P1036-法1.dfs组合 法2.combinations( )
  • springboot入门-service层构造器注入原理
  • 数据库设置外键的作用
  • 闲暇时间的“堕落”
  • 俄罗斯准备在没有先决条件的情况下与乌克兰进行谈判
  • 最高法报告重申保护创新主体权益:加大侵权损害赔偿力度
  • 重新认识中国女性|婚姻,古代传统家庭再生产的根本之道
  • 蚂蚁集团将向全体股东分红
  • 山西10岁男孩遭生母和继父殴打遇害,案件庭审延期