本文目录导读:

- 使用
java.util.Timer(基础、简单) - 使用
ScheduledExecutorService(推荐单机场景) - 使用 Spring 的
@Scheduled注解(企业级最常用) - 使用 Quartz 框架(复杂场景、分布式)
- 各方案对比总结
- 常见Cron表达式示例
Java中实现定时任务有多种方式,从简单到复杂、从单机到分布式,各有适用场景,以下是几种最常用的实现方案及具体案例:
使用 java.util.Timer(基础、简单)
这是JDK自带的定时器,适合简单的单机任务。
import java.util.Timer;
import java.util.TimerTask;
public class TimerDemo {
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);
// 程序运行10秒后停止
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
timer.cancel();
}
}
缺点:所有任务使用单线程,一个任务异常会影响其他任务;不支持Cron表达式。
使用 ScheduledExecutorService(推荐单机场景)
线程池实现的定时任务,性能更好,支持多线程并发。
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledExecutorDemo {
public static void main(String[] args) {
// 创建支持定时任务的线程池
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
// 任务1:固定速率执行(延迟1秒,每2秒执行一次)
executor.scheduleAtFixedRate(() -> {
System.out.println("任务1执行: " + Thread.currentThread().getName()
+ " - " + System.currentTimeMillis());
}, 1, 2, TimeUnit.SECONDS);
// 任务2:固定延迟执行(任务结束后固定延迟再执行)
executor.scheduleWithFixedDelay(() -> {
try {
Thread.sleep(1000); // 模拟任务耗时
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务2执行: " + Thread.currentThread().getName());
}, 1, 3, TimeUnit.SECONDS);
// 让程序运行一段时间
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
executor.shutdown();
}
}
特点:支持多线程、异常处理更灵活、可返回Future。
使用 Spring 的 @Scheduled 注解(企业级最常用)
在Spring Boot项目中,这是最常用、最优雅的方式。
1 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
2 启动类启用定时任务
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);
}
}
3 编写定时任务
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component
public class ScheduledTasks {
// 1. 固定延迟:任务结束后延迟2秒再执行
@Scheduled(fixedDelay = 2000)
public void taskWithFixedDelay() {
System.out.println("fixedDelay任务: " + LocalDateTime.now());
}
// 2. 固定速率:每3秒执行一次(不等待上一个任务完成)
@Scheduled(fixedRate = 3000)
public void taskWithFixedRate() {
System.out.println("fixedRate任务: " + LocalDateTime.now());
}
// 3. 使用Cron表达式:每天10:15执行
@Scheduled(cron = "0 15 10 * * ?")
public void taskWithCron() {
System.out.println("Cron任务: 每天10:15执行 - " + LocalDateTime.now());
}
// 4. 初始延迟:启动后5秒开始,之后每5秒执行
@Scheduled(initialDelay = 5000, fixedRate = 5000)
public void taskWithInitialDelay() {
System.out.println("延迟任务: " + LocalDateTime.now());
}
}
4 配置线程池(可选)
避免定时任务阻塞主线程,可自定义线程池:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@Configuration
public class SchedulingConfig {
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(5);
taskScheduler.setThreadNamePrefix("task-");
return taskScheduler;
}
}
使用 Quartz 框架(复杂场景、分布式)
适合需要持久化、集群、动态管理等复杂场景。
1 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
2 创建任务类
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
public class MyQuartzJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
System.out.println("Quartz任务执行: " + System.currentTimeMillis());
// 获取参数
String param = context.getJobDetail().getJobDataMap().getString("param");
System.out.println("参数: " + param);
}
}
3 配置定时器
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class QuartzConfig {
@Bean
public JobDetail myJobDetail() {
// 定义任务,绑定JobData参数
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("param", "hello");
return JobBuilder.newJob(MyQuartzJob.class)
.withIdentity("myJob", "group1")
.usingJobData(jobDataMap)
.storeDurably()
.build();
}
@Bean
public Trigger myTrigger() {
// 定义触发器,Cron表达式:每5秒执行一次
CronScheduleBuilder scheduleBuilder =
CronScheduleBuilder.cronSchedule("0/5 * * * * ?");
return TriggerBuilder.newTrigger()
.forJob(myJobDetail())
.withIdentity("myTrigger", "group1")
.withSchedule(scheduleBuilder)
.build();
}
}
各方案对比总结
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Timer | 简单、原生支持 | 单线程、异常影响大 | 极简单场景、JDK1.3+ |
| ScheduledExecutorService | 线程池、异常隔离 | 不支持Cron | 单机中等复杂度 |
| @Scheduled | 注解开发、Cron支持 | 默认单线程 | Spring Boot项目首选 |
| Quartz | 持久化、集群、动态管理 | 配置复杂、依赖重 | 企业级分布式场景 |
常见Cron表达式示例
0 0 12 * * ? - 每天中午12点
0 0/5 * * * ? - 每5分钟
0 0 8-18 * * ? - 每天8点到18点每小时执行
0 0 0 1 * ? - 每月1号零点
0 15 10 ? * 1-5 - 周一到周五10:15
0 0/30 9-17 * * ? - 9点到17点之间每30分钟
推荐选择:如果是Spring Boot项目,优先使用@Scheduled注解,简单高效;如果需要集群或持久化,再考虑Quartz。