Java Cron 表达式使用教程
一、什么是 Cron 表达式
Cron 表达式是一种用于配置定时任务执行时间的字符串格式,由 6~7 个字段组成,定义了任务在何时执行。
在 Java 中,Cron 表达式广泛应用于:
- Spring Task (
@Scheduled) - Quartz Scheduler
- xxl-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 |
|
|
月 |
1-12 / JAN-DEC |
|
|
周 |
0-7 / SUN-SAT |
|
|
年 |
1970-2099 |
|
特殊字符详解
|
字符 |
含义 |
示例 |
|
|
任意值,每... |
|
|
|
不指定(日和周互斥) |
|
|
|
范围 |
|
|
|
列表 |
|
|
|
步长/间隔 |
|
|
|
最后(Last) |
|
|
|
工作日(Weekday) |
|
|
|
第几个周几 |
|
四、常用 Cron 表达式示例
基础周期任务
|
表达式 |
说明 |
|
|
每秒执行 |
|
|
每1分钟执行(整分触发) |
|
|
每5分钟执行 |
|
|
每小时执行(整点) |
|
|
每2小时执行 |
|
|
每天0点执行 |
|
|
每天中午12点执行 |
特定时间点
|
表达式 |
说明 |
|
|
工作日8:30执行 |
|
|
每天9点和18点执行 |
|
|
每月最后一天10点执行 |
|
|
每月1号10点执行 |
|
|
每月第1个周一10点执行 |
|
|
每月15号10点执行 |
|
|
每月15日最近工作日10点执行 |
复杂场景
|
表达式 |
说明 |
|
|
每年1月1日0点执行 |
|
|
每季度首月1日执行(1,4,7,10月) |
|
|
每月最后一个周五0点执行 |
|
|
每月最后一个工作日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>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
定义 Job
public 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. 创建 Trigger(Cron 表达式)
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
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
更多推荐




所有评论(0)