【Java】任务调度的几种方式
最近需要用到任务调度,让我们初步了解一下吧。定时任务的方法包括:
- 使用Java原生定时任务
- 使用使用SpringBoot原生任务
- 使用框架:Quartz /Elastic Job / XXL-JOB
框架 | 核心优势 | 适用场景 | 示例依赖 |
---|---|---|---|
Quartz | 支持持久化、集群、复杂Cron规则 | 企业级分布式调度 | quartz 2.3.2 |
Elastic Job | 弹性调度、分片处理、故障转移 | 大数据量分布式任务 | elasticjob-lite-core 3.0.1 |
XXL-JOB | 管理界面、任务路由、失败告警 | 中小型项目可视化调度 | xxl-job-core 2.3.0 |
Java的原生定时任务
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("TimerTask执行");
}
}, 1000, 2000); // 延迟1秒,每2秒执行一次
ScheduledExecutorService executor = Executors.newScheduledThreadPool(3);
executor.scheduleAtFixedRate(
() -> System.out.println("ScheduledExecutor执行"),
1, 2, TimeUnit.SECONDS
);
方法 | 特点 |
---|---|
Timer | 单线程执行,任务阻塞会导致后续任务延迟 适用于简单场景,无复杂调度需求 |
ScheduledExecutorService | 基于线程池(可配置并发数) 支持任务异常处理,避免单任务失败影响全局 |
SpringBoot下简单的任务调度Scheduled
https://www.cnblogs.com/luyj00436/p/18710912 。只需要为任务添加@Secheduled
,并在启动类中添加@EnableScheduling
。
Quartz
quartz是开源的任务调度库,它允许开发者通过配置或编程方式定义、调度和管理任务。 quartz的核心功能包含:
- 任务调度:定义任务的执行计划,并在指定时间或周期性执行任务。
- 任务管理:管理和控制任务的生命周期,如启动、暂停、删除等。
- 持久化:支持将任务的状态持久化到数据库,以便在应用重启后恢复任务状态。
核心框架
组件 | 描述 | 关键特性 | 实现方式 |
---|---|---|---|
Job | 定义任务执行逻辑 | - 需实现Job 接口,重写execute() 方法 - 开发者自定义业务逻辑(如数据处理、API调用等) |
通过JobBuilder 绑定具体实现类(如HelloJob.class ) |
JobDetail | 封装Job的元数据 | - 包含任务名称、所属组、Job类信息 - 通过反射实例化Job对象 - 支持传递参数(通过JobDataMap ) |
使用JobBuilder.newJob() 构建,例如: JobBuilder.newJob(HelloJob.class).build() |
Trigger | 定义任务触发规则 | - 支持SimpleTrigger (固定间隔/单次触发) - 支持CronTrigger (基于Cron表达式) - 可设置优先级和过期时间 |
通过TriggerBuilder 配置,例如: TriggerBuilder.newTrigger().withSchedule(...) |
Scheduler | 调度器核心容器,协调任务执行 | - 注册并管理JobDetail 和Trigger - 支持集群和持久化 - 提供任务暂停、恢复、删除等操作接口 |
通过StdSchedulerFactory 获取实例,例如: StdSchedulerFactory.getDefaultScheduler() |
快速入门
-
在Maven项目中引入quartz依赖。
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version> </dependency>
-
定义job类
public class HelloQuartz implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { System.out.println("[quartz][当前时间]:" + LocalDateTime.now()); } }
-
设置任务的配置
@Configuration public class QuartzConfig { /** * 1.定义任务细节 * @return */ @Bean public SchedulerFactory jobDetialFactoryBean() throws SchedulerException { // 1. 创建调度器工厂 SchedulerFactory schedulerFactory = new org.quartz.impl.StdSchedulerFactory(); Scheduler scheduler = schedulerFactory.getScheduler(); // 2. 定义任务细节 org.quartz.JobDetail jobDetail = JobBuilder.newJob(HelloQuartz.class) .withIdentity("MyJob", "group1") .usingJobData("key","value") .build(); // 3. 定义触发 Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("MyTrigger", "group1") .startNow() // 触发开始时间 .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(5) // 每5s一次 .repeatForever()) .build(); // 将任务细节和触发器注册到调度器中 scheduler.scheduleJob(jobDetail, trigger); // 启动调度器 scheduler.start(); return schedulerFactory; } }
或
@Configuration
public class QuartzConfig {
/**
* 设置SchedulerFactory 代理工程
* @return
*/
@Bean
public SchedulerFactory getSchedulerFactory() throws SchedulerException {
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
// 设置任务 和触发器
scheduler.scheduleJob(getJobDetail(),getTrigger());
// 启动
scheduler.start();
return schedulerFactory;
}
/**
* 设置一个任务1
* @return
* @throws SchedulerException
*/
private JobDetail getJobDetail() throws SchedulerException {
JobDetail jobDetail = JobBuilder.newJob(HelloQuartz.class)
.withIdentity("MyJob","group1")
.usingJobData("key","value")
.storeDurably() // 设置当前任务支持持久化
.build();
return jobDetail;
}
/**
* 定义触发器1
* @return
* @throws SchedulerException
*/
private Trigger getTrigger() throws SchedulerException {
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("MyTrigger","group1")
.startNow() // 触发器开始时间
.withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")) // Corn表达式,每5秒执行一次
.build();
return trigger;
}
}
此时,quart能够定时执行任务
XXL-Job 任务使用教程
xxl-Job入门教程:https://www.cnblogs.com/luyj00436/p/18780550
Elastic Job
参考教程,发现Elastic Job强依赖Zooker,在运维复杂度上高于Xxl-Job,社区活跃度上低于Xxl-Job。毕竟高吞吐量,分片式任务的场景并没有那么多。不过,还是简单入门Elastic Job吧。
我也简单的入了个门就走出来了:https://www.cnblogs.com/luyj00436/p/18781122
有志者,事竟成,破釜沉舟,百二秦关终属楚; 苦心人,天不负,卧薪尝胆,三千越甲可吞吴。