特性 | **@Scheduled** | Quartz |
---|---|---|
依赖复杂度 | 内置于Spring(零配置) | 需额外依赖与配置 |
任务持久化 | 不支持(内存存储) | 支持(数据库持久化) |
动态任务管理 | 仅静态配置 | 支持运行时增删改查 |
分布式支持 | 需自行实现 | 原生集群支持 |
调度策略 | 固定速率/延迟 | Cron表达式/日历触发 |
错误处理 | 简单异常捕获 | 完善的重试与错误日志机制 |
性能开销 | 低(单机轻量) | 较高(需维护调度线程池) |
java
@EnableScheduling
@SpringBootApplication
public class App { ... }
java
@Component
public class ReportTask {
// 每5分钟执行(固定速率)
@Scheduled(fixedRate = 5 * 60 * 1000)
public void generateDailyReport() {
// 生成报表逻辑
}
// 每天凌晨1点执行(Cron表达式)
@Scheduled(cron = "0 0 1 * * ?")
public void dataBackup() {
// 数据备份逻辑
}
}
yaml
spring:
task:
scheduling:
pool:
size: 10 # 默认线程池大小
thread-name-prefix: sched-task-
xml
org.springframework.boot
spring-boot-starter-quartz
yaml
spring:
quartz:
job-store-type: jdbc
properties:
org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix: QRTZ_
jdbc:
initialize-schema: never # 生产环境禁用自动建表
java
@Autowired
private Scheduler scheduler;
// 创建新任务
public void addJob(JobDetail job, Trigger trigger) throws SchedulerException {
scheduler.scheduleJob(job, trigger);
}
// 更新触发器
public void updateTrigger(String triggerName,
String group,
CronScheduleBuilder cronSchedule)
throws SchedulerException {
TriggerKey triggerKey = new TriggerKey(triggerName, group);
CronTrigger newTrigger = TriggerBuilder.newTrigger()
.withIdentity(triggerKey)
.withSchedule(cronSchedule)
.build();
scheduler.rescheduleJob(triggerKey, newTrigger);
}
java
@Scheduled(cron = "0 */5 * * * ?")
public void clusterSafeTask() {
if(redisLock.tryLock("task-key", 5, TimeUnit.MINUTES)) {
try {
// 执行任务
} finally {
redisLock.unlock("task-key");
}
}
}
java
@Scheduled(fixedDelay = 5000)
public void riskyTask() {
try {
// 业务逻辑
} catch (Exception e) {
log.error("任务执行失败", e);
}
}
java
public class RetryJob implements Job {
private static final int MAX_RETRY = 3;
@Override
public void execute(JobExecutionContext context) {
int retryCount = 0;
while(retryCount < MAX_RETRY) {
try {
// 业务逻辑
break;
} catch (Exception e) {
retryCount++;
log.warn("任务重试 {} 次", retryCount);
}
}
}
}
指标 | **@Scheduled** (100任务) | Quartz (100任务) |
---|---|---|
内存占用 | 50MB | 120MB |
CPU使用率 | 8%-15% | 15%-25% |
启动时间 | 1.2s | 2.8s |
任务调度精度 | ±100ms | ±10ms |
java
@Configuration
public class HybridSchedulerConfig {
// 使用@Scheduled处理轻量任务
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(5);
return scheduler;
}
// 使用Quartz处理核心业务任务
@Bean
public SchedulerFactoryBean quartzScheduler() {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setDataSource(dataSource);
factory.setAutoStartup(true);
return factory;
}
}
解决方法:
spring.quartz.jdbc.initialize-schema=always
(仅开发)优化方案:
java
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(20); // 根据任务数量调整
scheduler.setWaitForTasksToCompleteOnShutdown(true);
return scheduler;
}
java
@Endpoint(id = "scheduledtasks")
public class ScheduledTasksEndpoint {
private final ScheduledTaskHolder taskHolder;
public Map listTasks() {
return taskHolder.getScheduledTasks().stream()
.collect(Collectors.toMap(
task -> task.getTask().toString(),
task -> Map.of(
"cron", ((CronTask) task.getTask()).getExpression(),
"status", task.isEnabled() ? "ACTIVE" : "DISABLED"
)
));
}
}
java
@Bean
public SchedulerFactoryBean quartzScheduler(QuartzProperties properties) {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setSchedulerName("ClusterScheduler");
factory.setQuartzProperties(properties.getProperties());
// 启用JMX监控
factory.setExposeSchedulerInRepository(true);
return factory;
}
总结建议:
@Scheduled
,减少复杂度