Java 中如何运行定时(cron)任务?

Java 跑 cron 定时任务的主流方案:Quartz Scheduler 完整示例(Maven 依赖、Job、cron 触发器)、Spring @Scheduled 简法、ScheduledExecutorService 轻量替代与 FAQ。

最佳实践
Java 中如何运行定时(cron)任务?封面

功能完整的方案用 Quartz Scheduler:加依赖 → 写一个实现 Job 接口的类 → 用 CronScheduleBuilder 绑定 cron 表达式启动调度器。 如果只是 Spring 项目里的简单定时需求,@Scheduled(cron = "...") 一行注解更省事。

方案一:Quartz Scheduler

1. 加 Maven 依赖

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.3.2</version>
</dependency>

2. 定义 Job

public class HelloJob implements Job {
    @Override
    public void execute(JobExecutionContext context) {
        System.out.println("Hello world! " + LocalDateTime.now());
    }
}

3. 用 cron 表达式调度

Scheduler scheduler = new StdSchedulerFactory().getScheduler();
scheduler.start();

JobDetail job = JobBuilder.newJob(HelloJob.class)
        .withIdentity("helloJob", "group1")
        .build();

Trigger trigger = TriggerBuilder.newTrigger()
        .withIdentity("helloTrigger", "group1")
        .withSchedule(CronScheduleBuilder.cronSchedule("0 * * * * ?"))  // 每分钟
        .build();

scheduler.scheduleJob(job, trigger);

注意 Quartz 的表达式是六/七字段(秒 分 时 日 月 星期 [年]),和 Linux crontab 的五字段不同:0 * * * * ? 表示每分钟第 0 秒。

Quartz 还支持 JDBC JobStore 持久化调度、集群部署、misfire 补偿——企业级定时任务平台的基本盘。

方案二:Spring 的 @Scheduled(更常用)

Spring 项目里大多数场景不需要 Quartz 的重量级能力:

@Component
public class ReportTask {

    @Scheduled(cron = "0 30 2 * * ?")   // 每天 2:30
    public void dailyReport() {
        // ...
    }
}

启动类加 @EnableScheduling。固定间隔用 @Scheduled(fixedRate = 300_000)(毫秒)。同样是六字段格式。

方案三:标准库轻量替代

只要"每 N 秒/分钟跑一次",不需要日历语义时:

ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(() -> doWork(), 0, 5, TimeUnit.MINUTES);

没有 cron 表达式,但零依赖、行为可控。

观测云对照

JVM 内的调度器和系统 cron 一样有"静默不跑"的风险,而且排查更难——线程池耗尽、上次执行卡死都会让后续任务无声延误。接入观测云 APM 后,可把定时任务方法埋点为 span,观测每次执行耗时与异常;任务日志统一采集后,用监控器做"预期窗口内无成功日志"的心跳告警,JVM 停顿、线程池打满导致的任务延误都能被兜住。

常见问题(FAQ)

Q:Quartz 表达式里的 ? 是什么?
A:? 表示"不指定",只能用在"日"和"星期"两个字段之一上——因为这两个字段同时指定会互相冲突。0 30 2 ? * MON 这类写法就是靠 ? 让位。

Q:fixedRate 和 fixedDelay 有什么区别?
A:fixedRate 按固定频率触发(不管上一次是否结束,可能并发);fixedDelay 是上一次结束后再等固定间隔。怕重叠用后者,或加锁/状态位。

Q:多实例部署时任务会重复执行吗?
A:会。@Scheduled 没有集群协调,每个实例都会触发。要么 Quartz + JDBC 集群模式,要么 ShedLock 之类加分布式锁。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台