← ClaudeAtlas

schedule-joblisted

Use when implementing 定时任务, @Scheduled, cron, XXL-JOB, Quartz, ShedLock, or cluster duplicate job execution. Do not use for 延迟关单 (backend-delay-job). Jobs must be idempotent.
1398281322-a11y/java-backend-guardrails · ★ 2 · AI & Automation · score 73
Install: claude install-skill 1398281322-a11y/java-backend-guardrails
# 定时任务 / 调度 ## When to Invoke 日切对账、账期结算批、补偿扫描、报表、面试「@Scheduled 集群会怎样」「Timer 和线程池调度区别」「XXL-JOB 分片」。 ## When NOT 下单 N 分钟关单、券过期这类 **一次性延迟** → `delay-job`(发延迟消息,禁止扫全表)。立刻异步解耦 → `mq-reliability`。任务线程池参数细节 → `thread-pool`。 ## 风险(面试考点) `java.util.Timer`:**单线程**;一个任务卡住后面全延迟;未捕获异常 **杀死 Timer 线程**,后续任务全停;基于绝对时钟,改系统时间会乱。JDK 文档写明用 `ScheduledThreadPoolExecutor` 替代。 Spring `@Scheduled` 默认 **线程池 size=1**(`spring.task.scheduling.pool.size`,Boot 2.1+)。一个慢 Job 堵住所有 cron。同一方法在单线程上不会重叠;**多实例每人一份调度器,任务会跑 N 遍**——这不是 Bug。 ShedLock / Redis 锁只能保证「同时最多一个」;`lockAtMostFor` 到期会把锁交给别人,长任务必须大于最坏耗时或可续期。锁不是幂等:任务仍要按业务键可重入。 XXL-JOB(官方能力,别背错): - **调度过期**:忽略(推荐)/ 立即补偿一次。补偿可能双跑,业务必须幂等。 - **阻塞处理**:单机串行(默认排队);丢弃后续;覆盖之前(会打断正在跑的)。 - **分片广播**:所有执行器都触发,用 `shardIndex/shardTotal` 切数据;不是「只跑一台」。 - 超时会中断任务,循环里要响应中断。失败重试次数 >0 时当重复执行。 Cron 时区写死 `Asia/Shanghai`。Spring 是 6 域(含秒)。`fixedRate` 按开始时间对齐,跑超周期会积压;`fixedDelay` ��上一次 **结束** 再等。 禁止用定时任务当关单主路径(见 `delay-job`)。补偿扫描只捞小窗口、带索引、LIMIT 批次。 ## 方案选型(轻量优先) | 场景 | 默认 | |------|------| | 单实例、几个轻量 Job | `@Scheduled` + 调大 scheduling pool | | 多实例、Job 少 | `@Scheduled` + ShedLock(或 Redisson 锁) | | 多实例、要控制台/分片/告警 | XXL-JOB | | 一次性延迟 | 不走本文件 | ```java @Scheduled(cron = "0 0 2 * * ?", zone = "Asia/Shanghai") @SchedulerLock(name = "settleDaily", lockAtMostFor = "50m", lockAtLeastFor = "1m") public void settle() { // 批次 LIMIT;幂等 uk;失败可重跑 } ``` XXL-JOB 大批量: ```java @XxlJob("verifyCompensate") public void compensate() { int idx = XxlJobHelper.getShardIndex(); int tota