Spring Boot 定时任务精确到毫秒级触发:实现每秒固定毫秒偏移执行
发布时间 - 2026-01-23 00:00:00 点击率:次本文介绍如何在 spring boot 中实现高精度定时任务,使 @scheduled 任务严格在每秒的指定毫秒时刻(如 xx:xx:xx.900)触发,摆脱系统启动时间依赖与 cron 秒级限制。
Spring 的 @Scheduled 注解默认支持 cron、fixedDelay 和 fixedRate 等方式,但它们均无法满足「每秒精准偏移 X 毫秒」的需求:
- cron = "* * * ? * *" 仅保证「每秒触发一次」,起始时刻取决于应用启动时间,且 JVM 调度和线程唤醒存在毫秒级延迟;
- fixedRate = 1000 同样以上一次任务开始/结束时间为基准,随执行耗时漂移,无法锚定绝对时间点(如每秒的 900ms)。
要实现真正与系统时钟对齐的定时行为(例如:20:00:00.900、20:00:01.900、20:00:02.900…),必须自定义 Trigger,并基于 System.currentTimeMillis() 或 Instant.now() 动态计算下一个绝对目标时间戳。
✅ 推荐方案:自定义 Trigger 实现毫秒级对齐
以下是一个生产就绪的轻量级实现,不依赖前次执行时间,而是始终对齐到「最近的整秒 + 指定毫秒」:
public class AlignedSecondTrigger implements Trigger {
private final int offsetMs; // 如 900,表示每秒第 900 毫秒触发
public A
lignedSecondTrigger(int offsetMs) {
if (offsetMs < 0 || offsetMs >= 1000) {
throw new IllegalArgumentException("offsetMs must be in [0, 999]");
}
this.offsetMs = offsetMs;
}
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
long now = System.currentTimeMillis();
// 计算当前时间所属的“整秒起点”(向下取整到秒)
long secondStart = now - (now % 1000);
// 目标时间 = 整秒起点 + offsetMs;若已过该时刻,则取下一秒
long target = secondStart + offsetMs;
if (target <= now) {
target += 1000; // 推迟到下一秒的对应毫秒点
}
return new Date(target);
}
}? 关键设计说明: 使用 System.currentTimeMillis() 获取当前绝对时间; 通过 now % 1000 剥离毫秒部分,得到本秒起始时间戳; 加上 offsetMs 得到目标时间;若该时间已过去(即当前毫秒 > offsetMs),则自动+1000ms跳至下一秒——确保严格按节奏推进,无累积误差。
? 配置任务:通过 SchedulingConfigurer 注册
@Configuration
@EnableScheduling
public class SchedulerConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar registrar) {
// 每秒在 .900 时刻执行
registrar.addTriggerTask(
() -> System.out.println("Fired at: " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss.SSS"))),
new AlignedSecondTrigger(900)
);
}
}⚠️ 注意事项与最佳实践
- 线程安全:Trigger.nextExecutionTime() 是无状态的,本实现完全线程安全;
- 任务执行耗时影响:此方案不规避重叠执行。若任务执行时间 > 1000ms,下一次触发仍会准时发生(可能并发)。如需防止并发,请在任务内加锁或改用 @Async + 队列控制;
- 时钟同步风险:若系统时间被 NTP 调整(如向后跳秒),可能导致单次跳过或重复。生产环境建议启用 adjtimex 平滑校时;
- 更高精度替代方案:对亚毫秒级要求场景(如金融行情推送),应考虑 Netty HashedWheelTimer、Quartz with custom Trigger 或专用实时调度器(如 Apache Flink CEP),Spring 内置调度器本质是 ThreadPoolTaskScheduler,底层仍受限于 JVM 线程调度粒度(通常 10–15ms)。
✅ 总结
通过实现 Trigger 接口并基于绝对时间动态计算下次执行点,可突破 Spring @Scheduled 的固有局限,实现稳定、可预测的毫秒级定时对齐。该方案简洁、无外部依赖、易于测试与维护,是 Spring Boot 应用中实现「每秒准点触发」的推荐实践。
# apache
# 金融
# red
# spring
# spring boot
# jvm
# 接口
# 线程
# 并发
# flink
# 执行时间
# 下一秒
# 自定义
# 是一个
# 前次
# 请在
# 更高
# 时间为
# 如需
# 跳过
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
香港服务器建站指南:外贸独立站搭建与跨境电商配置流程
如何用腾讯建站主机快速创建免费网站?
Laravel如何实现事件和监听器?(Event & Listener实战)
如何在阿里云购买域名并搭建网站?
JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)
网站制作大概要多少钱一个,做一个平台网站大概多少钱?
详解Huffman编码算法之Java实现
如何快速搭建虚拟主机网站?新手必看指南
Python自然语言搜索引擎项目教程_倒排索引查询优化案例
Laravel如何使用withoutEvents方法临时禁用模型事件
网站制作报价单模板图片,小松挖机官方网站报价?
香港服务器网站生成指南:免费资源整合与高速稳定配置方案
如何确保FTP站点访问权限与数据传输安全?
如何用景安虚拟主机手机版绑定域名建站?
iOS发送验证码倒计时应用
Laravel Debugbar怎么安装_Laravel调试工具栏配置指南
EditPlus中的正则表达式实战(6)
JS碰撞运动实现方法详解
JavaScript中如何操作剪贴板_ClipboardAPI怎么用
香港服务器如何优化才能显著提升网站加载速度?
如何快速生成橙子建站落地页链接?
VIVO手机上del键无效OnKeyListener不响应的原因及解决方法
java ZXing生成二维码及条码实例分享
js实现点击每个li节点,都弹出其文本值及修改
使用Dockerfile构建java web环境
Laravel如何实现多级无限分类_Laravel递归模型关联与树状数据输出【方法】
深圳网站制作培训,深圳哪些招聘网站比较好?
历史网站制作软件,华为如何找回被删除的网站?
手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?
JavaScript如何操作视频_媒体API怎么控制播放
Edge浏览器怎么启用睡眠标签页_节省电脑内存占用优化技巧
如何选择可靠的免备案建站服务器?
html5audio标签播放结束怎么触发事件_onended回调方法【教程】
JavaScript如何实现路由_前端路由原理是什么
如何快速重置建站主机并恢复默认配置?
详解CentOS6.5 安装 MySQL5.1.71的方法
大连网站制作公司哪家好一点,大连买房网站哪个好?
佛山企业网站制作公司有哪些,沟通100网上服务官网?
Laravel如何实现数据导出到PDF_Laravel使用snappy生成网页快照PDF【方案】
如何在Windows环境下新建FTP站点并设置权限?
Laravel如何使用Scope本地作用域_Laravel模型常用查询逻辑封装技巧【手册】
如何解决hover在ie6中的兼容性问题
Laravel怎么生成二维码图片_Laravel集成Simple-QrCode扩展包与参数设置【实战】
标准网站视频模板制作软件,现在有哪个网站的视频编辑素材最齐全的,背景音乐、音效等?
Laravel如何记录自定义日志?(Log频道配置)
手机网站制作与建设方案,手机网站如何建设?
Laravel的辅助函数有哪些_Laravel常用Helpers函数提高开发效率
宙斯浏览器文件分类查看教程 快速筛选视频文档与图片方法
Laravel distinct去重查询_Laravel Eloquent去重方法
Laravel怎么使用Blade模板引擎_Laravel模板继承与Component组件复用【手册】


