Java Cron 表达式使用教程

Java Cron 表达式使用教程 一、什么是 Cron 表达式Cron 表达式是一种用于配置定时任务执行时间的字符串格式由 6~7 个字段组成定义了任务在何时执行。在 Java 中Cron 表达式广泛应用于Spring Task(Scheduled)Quartz Schedulerxxl-job、Elastic-Job等分布式调度框架二、Cron 表达式结构标准 6 字段格式Spring/Quartz 通用┌───────────── 秒 (0-59) │ ┌───────────── 分 (0-59) │ │ ┌───────────── 时 (0-23) │ │ │ ┌───────────── 日 (1-31) │ │ │ │ ┌───────────── 月 (1-12 或 JAN-DEC) │ │ │ │ │ ┌───────────── 周 (0-7 或 SUN-SAT, 0/7周日) │ │ │ │ │ │ │ │ │ │ │ │ * * * * * *7 字段格式部分框架支持含年字段* * * * * * * │ │ │ │ │ │ │ │ │ │ │ │ │ └─ 年 (可选, 1970-2099) │ │ │ │ │ └─── 周 │ │ │ │ └───── 月 │ │ │ └─────── 日 │ │ └───────── 时 │ └─────────── 分 └───────────── 秒三、字段取值与特殊字符字段允许值特殊字符秒0-59, - * /分0-59, - * /时0-23, - * /日1-31, - * / ? L W月1-12 / JAN-DEC, - * /周0-7 / SUN-SAT, - * / ? L #年1970-2099, - * /特殊字符详解字符含义示例*任意值每...* * * * * *每秒执行?不指定日和周互斥0 0 1 * * ?每月1日执行不指定周-范围10-2010到20,列表1,3,51、3、5/步长/间隔0/5从0开始每5个单位L最后LastL月末最后一天6L最后一个周五W工作日Weekday15W最接近15日的工作日#第几个周几2#3第3个周一四、常用 Cron 表达式示例基础周期任务表达式说明0/1 * * * * ?每秒执行0 * * * * ?每1分钟执行整分触发0 0/5 * * * ?每5分钟执行0 0 * * * ?每小时执行整点0 0 0/2 * * ?每2小时执行0 0 0 * * ?每天0点执行0 0 12 * * ?每天中午12点执行特定时间点表达式说明0 30 8 ? * MON-FRI工作日8:30执行0 0 9,18 * * ?每天9点和18点执行0 0 10 L * ?每月最后一天10点执行0 0 10 1 * ?每月1号10点执行0 0 10 ? * 2#1每月第1个周一10点执行0 0 10 15 * ?每月15号10点执行0 0 10 15W * ?每月15日最近工作日10点执行复杂场景表达式说明0 0 0 1 1 ? *每年1月1日0点执行0 0 0 1 1/3 ?每季度首月1日执行1,4,7,10月0 0 0 ? * 6L每月最后一个周五0点执行0 0 0 LW * ?每月最后一个工作日0点执行五、Spring Boot 实战1. 启用定时任务SpringBootApplication EnableScheduling // 开启定时任务 public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }2. 创建定时任务Component Slf4j public class ScheduledTasks { /** * 每5秒执行一次 */ Scheduled(cron 0/5 * * * * ?) public void taskEvery5Seconds() { log.info(每5秒执行当前时间{}, LocalDateTime.now()); } /** * 每天凌晨1点执行数据清理 */ Scheduled(cron 0 0 1 * * ?) public void dailyCleanup() { log.info(开始每日数据清理...); // 执行清理逻辑 } /** * 工作日早8点半发送日报 */ Scheduled(cron 0 30 8 ? * MON-FRI) public void sendDailyReport() { log.info(发送工作日报...); } /** * 每月1号0点生成月报 */ Scheduled(cron 0 0 0 1 * ?) public void generateMonthlyReport() { log.info(生成月度报表...); } }3. 动态配置 Cron 表达式Component Slf4j public class DynamicScheduledTask implements SchedulingConfigurer { Autowired private TaskConfigRepository configRepository; // 从数据库读取配置 Override public void configureTasks(ScheduledTaskRegistrar registrar) { registrar.addTriggerTask( this::executeTask, triggerContext - { // 从数据库获取最新cron表达式 String cron configRepository.findCronByTaskName(dataSync); if (StringUtils.isEmpty(cron)) { cron 0 0/30 * * * ?; // 默认每30分钟 } return new CronTrigger(cron).nextExecutionTime(triggerContext); } ); } public void executeTask() { log.info(执行动态配置的任务时间{}, LocalDateTime.now()); } }4. 异步定时任务防止阻塞Configuration EnableAsync // 开启异步 EnableScheduling public class AsyncConfig { Bean(taskExecutor) public Executor taskExecutor() { ThreadPoolTaskExecutor executor new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); executor.setMaxPoolSize(20); executor.setQueueCapacity(200); executor.setThreadNamePrefix(task-); executor.initialize(); return executor; } } Component public class AsyncScheduledTasks { Async(taskExecutor) Scheduled(cron 0 0/1 * * * ?) public void asyncTask() { // 长时间任务不会阻塞其他定时任务 log.info(异步任务开始...); Thread.sleep(10000); // 模拟耗时操作 log.info(异步任务结束...); } }六、Quartz 框架使用Maven 依赖dependency groupIdorg.quartz-scheduler/groupId artifactIdquartz/artifactId version2.3.2/version /dependency定义 Jobpublic class DataSyncJob implements Job { Override public void execute(JobExecutionContext context) throws JobExecutionException { JobDataMap data context.getJobDetail().getJobDataMap(); String param data.getString(param); System.out.println(Quartz Job 执行参数 param 时间 new Date()); } }调度配置public class QuartzDemo { public static void main(String[] args) throws Exception { // 1. 创建调度器 Scheduler scheduler StdSchedulerFactory.getDefaultScheduler(); scheduler.start(); // 2. 创建 JobDetail JobDetail job JobBuilder.newJob(DataSyncJob.class) .withIdentity(dataSyncJob, group1) .usingJobData(param, user_data) .build(); // 3. 创建 TriggerCron 表达式 CronTrigger trigger TriggerBuilder.newTrigger() .withIdentity(dataSyncTrigger, group1) .withSchedule(CronScheduleBuilder.cronSchedule(0 0/5 * * * ?)) .build(); // 4. 调度执行 scheduler.scheduleJob(job, trigger); // 保持运行 Thread.sleep(100000); scheduler.shutdown(); } }七、常见问题与注意事项⚠️ 重要提醒日和周字段互斥不能同时指定具体值必须有一个为?❌0 0 1 1 * 1错误同时指定了日和周✅0 0 1 1 * ?正确指定日周用?Quartz vs Spring 差异Spring 默认6字段无年Quartz 支持7字段含年时区问题Scheduled(cron 0 0 0 * * ?, zone Asia/Shanghai)任务重叠默认单线程长任务会阻塞后续执行建议使用Async或线程池集群环境单机Scheduled会多节点重复执行需用分布式锁或 Quartz 集群模式八、快速参考卡片常用表达式速查 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 每秒 0/1 * * * * ? 每5秒 0/5 * * * * ? 每分钟 0 * * * * ? 每5分钟 0 0/5 * * * ? 每小时 0 0 * * * ? 每2小时 0 0 0/2 * * ? 每天0点 0 0 0 * * ? 每天8点 0 0 8 * * ? 工作日8:30 0 30 8 ? * MON-FRI 每月1日0点 0 0 0 1 * ? 每月最后1天 0 0 0 L * ? 每周日0点 0 0 0 ? * 1 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━