Java 定时任务 - 从基础到高阶使用 - 从 Timer 到 Quart
在 Java 开发中,定时任务是常见需求,比如定时发送邮件、清理日志、同步数据等。从简单的 Timer 到企业级的 Quartz Scheduler。
基础:使用 Timer 和 TimerTask
Timer 和 TimerTask 是 Java 提供的内置工具,适合简单场景。Timer 负责调度,TimerTask 定义任务逻辑。
示例代码
import java.util.Timer;
import java.util.TimerTask;
public class TimerExample {
public static void main(String[] args) {
Timer timer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
System.out.println("任务执行时间: " + System.currentTimeMillis());
}
};
// 延迟 1 秒后执行,每 2 秒重复执行
timer.schedule(task, 1000, 2000);
// 10 秒后停止
new Timer().schedule(new TimerTask() {
@Override
public void run() {
timer.cancel();
System.out.println("Timer 停止");
}
}, 10000);
}
}
代码解释
• 创建 Timer 和 TimerTask:
Timer 是调度器,负责管理任务的执行时间。
TimerTask 是一个抽象类,通过重写 run() 方法定义任务逻辑。
• 调度任务:
schedule(task, delay, period):延迟 delay 毫秒后执行任务,每隔 period 毫秒重复执行。
• 停止 Timer:
使用 timer.cancel() 停止调度器。
优缺点
• 优点:简单易用,无需额外依赖。
• 缺点:单线程执行,任务阻塞会影响后续任务;异常可能导致整个 Timer 终止。
适用场景
轻量级任务,如简单的状态检查或日志清理。
中级:使用 ScheduledExecutorService
ScheduledExecutorService 是 Java 并发包(java.util.concurrent)中的工具,基于线程池,支持多任务并发执行,比 Timer 更现代、更稳定。
示例代码
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledExecutorExample {
public static void main(String[] args) {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
Runnable task = () -> System.out.println("任务执行时间: " + System.currentTimeMillis());
// 延迟 1 秒后执行,每 2 秒重复(固定频率)
scheduler.scheduleAtFixedRate(task, 1, 2, TimeUnit.SECONDS);
// 10 秒后停止
scheduler.schedule(() -> {
scheduler.shutdown();
System.out.println("Scheduler 停止");
}, 10, TimeUnit.SECONDS);
}
}
代码解释
• 创建调度器:
Executors.newScheduledThreadPool(2) 创建一个容量为 2 的线程池,支持并发执行。
• 调度任务:
scheduleAtFixedRate(task, initialDelay, period, unit):延迟 initialDelay 后执行任务,每隔 period 时间单位重复执行。
• 停止调度器:
使用 scheduler.shutdown() 优雅关闭线程池。
• 固定频率 vs 固定延迟:
scheduleAtFixedRate:固定时间间隔执行,不考虑任务耗时。
scheduleWithFixedDelay:任务执行完后,等待固定延迟再执行下一次。
优缺点
• 优点:支持多线程并发,异常不会影响调度器,调度方式灵活。
• 缺点:不支持 cron 表达式,需手动管理线程池。
适用场景
需要并发执行多个定时任务,如批量数据处理、状态监控。
高阶:使用 Spring 的 @Scheduled
在 Spring 项目中,@Scheduled 注解是实现定时任务的首选,简单易用,支持 cron 表达式,适合复杂调度需求。
示例代码
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Configuration
@EnableScheduling
@Component
public class SpringScheduledExample {
// 每 5 秒执行一次
@Scheduled(fixedRate = 5000)
public void fixedRateTask() {
System.out.println("固定频率任务: " + System.currentTimeMillis());
}
// 每 5 秒延迟执行(任务完成后等待 5 秒)
@Scheduled(fixedDelay = 5000)
public void fixedDelayTask() {
System.out.println("固定延迟任务: " + System.currentTimeMillis());
}
// 使用 cron 表达式,每分钟执行一次
@Scheduled(cron = "0 * * * * ?")
public void cronTask() {
System.out.println("Cron 任务: " + System.currentTimeMillis());
}
}
代码解释
• 启用调度:
@EnableScheduling 注解启用 Spring 的定时任务支持。
• 定义任务:
@Scheduled(fixedRate = 5000):每 5 秒执行一次任务。
@Scheduled(fixedDelay = 5000):任务完成后,等待 5 秒再执行下一次。
@Scheduled(cron = “0 * * * * ?”):使用 cron 表达式,每分钟的第 0 秒执行。
• Cron 表达式:
格式:秒 分 时 天 月 星期。
配置线程池(可选)
Spring 默认使用单线程调度器,任务阻塞可能导致延迟。可以通过自定义线程池优化:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@Configuration
public class SchedulerConfig {
@Bean
public ThreadPoolTaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(10); // 设置线程池大小
scheduler.setThreadNamePrefix("scheduled-task-");
return scheduler;
}
}
代码解释
• ThreadPoolTaskScheduler:Spring 提供的线程池调度器。
• setPoolSize(10):设置线程池大小为 10,支持并发执行。
• setThreadNamePrefix:设置线程名前缀,便于日志追踪。
优缺点
• 优点:注解驱动,配置简单;支持 cron 表达式;与 Spring 生态无缝集成。
• 缺点:依赖 Spring 框架,分布式场景需额外扩展。
适用场景
Spring 项目的定时任务,如缓存刷新、数据同步。
进阶:使用 Quartz Scheduler
Quartz 是一个功能强大的开源调度框架,适合企业级复杂场景,支持分布式调度、任务持久化和动态管理。
示例代码(Spring 集成 Quartz)
1. 添加依赖(pom.xml)
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.3.22</version>
</dependency>
2. 定义 Job
import org.quartz.Job;
import org.quartz.JobExecutionContext;
public class MyQuartzJob implements Job {
@Override
public void execute(JobExecutionContext context) {
System.out.println("Quartz Job 执行: " + System.currentTimeMillis());
}
}
3. 配置 Quartz
import org.quartz.JobDetail;
import org.quartz.Trigger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
@Configuration
public class QuartzConfig {
@Bean
public JobDetailFactoryBean jobDetail() {
JobDetailFactoryBean factory = new JobDetailFactoryBean();
factory.setJobClass(MyQuartzJob.class);
factory.setDurability(true);
return factory;
}
@Bean
public CronTriggerFactoryBean trigger(JobDetail jobDetail) {
CronTriggerFactoryBean factory = new CronTriggerFactoryBean();
factory.setJobDetail(jobDetail);
factory.setCronExpression("0/5 * * * * ?"); // 每 5 秒执行
return factory;
}
@Bean
public SchedulerFactoryBean scheduler(Trigger trigger, JobDetail jobDetail) {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setTriggers(trigger);
factory.setJobDetails(jobDetail);
return factory;
}
}
代码解释
• Job 定义:
MyQuartzJob 实现 Job 接口,重写 execute 方法定义任务逻辑。
• JobDetail 配置:
JobDetailFactoryBean 用于创建 JobDetail,绑定具体的 Job 类。
setDurability(true):即使没有触发器,Job 也会保留。
• Trigger 配置:
CronTriggerFactoryBean 定义触发器,使用 cron 表达式 0/5 * * * * ?(每 5 秒触发)。
• Scheduler 配置:
SchedulerFactoryBean 整合 Job 和 Trigger,启动调度。
优缺点
• 优点:支持复杂调度、任务持久化、分布式调度;动态管理任务。
• 缺点:配置复杂,学习成本较高。
适用场景
• 企业级应用,如订单处理、报表生成。
• 分布式系统或需要动态调整任务的场景。
结语
选择建议:
• 简单任务:用 Timer 或 ScheduledExecutorService,轻量快速。
• Spring 项目:首选 @Scheduled,简单高效。
• 企业级复杂调度:选择 Quartz 或分布式框架(如 XXL-Job)。
注意事项
• 异常处理:在任务中捕获异常,避免调度器崩溃;记录日志便于排查问题。
• 资源管理:确保线程池或调度器及时关闭,释放资源。
• 性能优化:根据任务量调整线程池大小;对于大数据量任务,考虑分片或异步执行。
更多推荐

所有评论(0)