本文目录导读:

- 基础方案:使用
java.util.Timer - 企业级方案:
ScheduledExecutorService(推荐) - Spring Boot集成 Quartz(最强大,支持Cron)
- Spring Boot @Scheduled 注解(简单实用,推荐)
- 分布式场景:Redis + Redisson的分布式调度
- 选择建议
在Java中实现定时任务有多种方式,从简单到复杂,根据你的需求场景选择合适的方法,以下是几种主流的实现方案:
基础方案:使用 java.util.Timer
适合简单的单次或固定周期任务,不需要复杂调度。
import java.util.Timer;
import java.util.TimerTask;
public class TimerExample {
public static void main(String[] args) {
Timer timer = new Timer("MyTimer");
// 延迟1秒后执行,然后每3秒执行一次
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("任务执行中..." + System.currentTimeMillis());
}
}, 1000, 3000);
// 如果需要停止任务
// timer.cancel();
}
}
缺点:所有任务共用一个线程,一个任务异常会影响其他任务;不支持cron表达式。
企业级方案:ScheduledExecutorService(推荐)
从Java 5开始引入,基于线程池,性能更好,更稳定。
import java.util.concurrent.*;
public class ScheduledExecutorExample {
public static void main(String[] args) throws InterruptedException {
// 创建线程池,核心线程数2
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
// 一次性任务:延迟5秒执行
scheduler.schedule(() -> {
System.out.println("一次性任务执行:" + System.currentTimeMillis());
}, 5, TimeUnit.SECONDS);
// 固定延迟任务:上次执行完后延迟3秒再执行
scheduler.scheduleWithFixedDelay(() -> {
System.out.println("固定延迟任务:" + System.currentTimeMillis());
try {
Thread.sleep(2000); // 模拟任务执行耗时
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}, 0, 3, TimeUnit.SECONDS);
// 固定频率任务:每2秒执行一次,不受任务耗时影响
scheduler.scheduleAtFixedRate(() -> {
System.out.println("固定频率任务:" + System.currentTimeMillis());
}, 0, 2, TimeUnit.SECONDS);
// 让主线程运行一段时间再关闭
Thread.sleep(15000);
scheduler.shutdown();
}
}
优点:基于线程池,支持多任务并行;异常处理更灵活;适合生产环境。
Spring Boot集成 Quartz(最强大,支持Cron)
适合复杂的定时任务调度,如“每天上午10点执行”等。
添加依赖(pom.xml)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
创建任务类
import org.quartz.Job;
import org.quartz.JobExecutionContext;
public class MyQuartzJob implements Job {
@Override
public void execute(JobExecutionContext context) {
System.out.println("Quartz任务执行:" + System.currentTimeMillis());
// 业务逻辑代码
}
}
配置调度器
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class QuartzConfig {
@Bean
public JobDetail myJobDetail() {
return JobBuilder.newJob(MyQuartzJob.class)
.withIdentity("myJob", "group1")
.storeDurably()
.build();
}
@Bean
public Trigger myTrigger() {
// Cron表达式:每天上午10:15执行
// 格式: 秒 分 时 日 月 周 [年]
String cronExpression = "0 15 10 * * ?";
return TriggerBuilder.newTrigger()
.forJob(myJobDetail())
.withIdentity("myTrigger", "group1")
.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))
.build();
}
}
本机测试用的Cron示例
// 每5秒执行一次 "*/5 * * * * ?" // 每天中午12点整执行 "0 0 12 * * ?" // 每周一至周五上午10:30执行 "0 30 10 ? * MON-FRI"
Spring Boot @Scheduled 注解(简单实用,推荐)
适合轻量级应用,Spring Boot原生支持,无需额外依赖。
启用定时任务
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling // 启用定时任务
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
定义定时任务
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ScheduledTasks {
// 固定频率:每5秒执行一次(从任务开始计时)
@Scheduled(fixedRate = 5000)
public void reportCurrentTime() {
System.out.println("固定频率执行:" + System.currentTimeMillis());
}
// 固定延迟:上次执行完成后延迟3秒再执行
@Scheduled(fixedDelay = 3000)
public void processData() {
System.out.println("固定延迟执行:" + System.currentTimeMillis());
// 模拟耗时操作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
// 使用Cron表达式:每天上午9:30执行
@Scheduled(cron = "0 30 9 * * ?")
public void dailyReport() {
System.out.println("每日报告生成:" + System.currentTimeMillis());
}
// 带初始延迟:延迟10秒后,再每2秒执行一次
@Scheduled(fixedRate = 2000, initialDelay = 10000)
public void delayedTask() {
System.out.println("延迟后执行:" + System.currentTimeMillis());
}
}
注意事项:
- 默认所有任务共用一个线程池(线程数为1),可通过配置修改
- 方法不能有参数,返回类型为void
配置线程池(可选)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import java.util.concurrent.Executors;
@Configuration
public class SchedulerConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
// 设置线程池大小,避免一个任务阻塞其他任务
taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
}
}
分布式场景:Redis + Redisson的分布式调度
适合多实例部署的微服务,避免任务重复执行。
import org.redisson.api.RScheduledExecutorService;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class DistributedScheduler {
@Autowired
private RedissonClient redissonClient;
public void scheduleDistributedTask() {
RScheduledExecutorService executor = redissonClient.getExecutorService("myTasks");
// 提交一个延迟任务,只会被一个实例执行
executor.schedule(() -> {
System.out.println("分布式定时任务执行,当前实例:" + System.currentTimeMillis());
// 业务逻辑
}, 10, java.util.concurrent.TimeUnit.SECONDS);
}
}
选择建议
| 场景 | 推荐方案 |
|---|---|
| 简单单次/固定周期任务 | Timer 或 ScheduledExecutorService |
| Spring Boot项目,简单任务 | @Scheduled 注解 |
| 复杂调度(Cron表达式) | Spring Boot + Quartz |
| 大规模、高可用分布式系统 | Quartz集群 或 分布式调度框架(xxl-job, Elastic-Job) |
| 微服务多实例防重复执行 | Redis分布式锁 + @Scheduled |
我个人最推荐 Spring Boot的 @Scheduled 注解,简单高效,日常80%的需求都能满足,如果需要Cron表达式支持复杂调度,配合Quartz是业界标准方案。