本文目录导读:

- 使用 ScheduledExecutorService(推荐)
- 使用 Timer 和 TimerTask
- 使用 Quartz 框架
- 使用 Spring 的 @Scheduled 注解(Spring Boot)
- 生产环境定时任务管理器
- 常用CRON表达式示例
- 选择建议
我来提供一个完整的Java定时任务调度案例,包含多种实现方式:
使用 ScheduledExecutorService(推荐)
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledExecutorExample {
private static final DateTimeFormatter FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) {
// 创建调度线程池
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
// 1. 延迟5秒后执行一次
scheduler.schedule(() -> {
System.out.println("[" + getCurrentTime() + "] 一次性任务执行");
}, 5, TimeUnit.SECONDS);
// 2. 固定频率执行(每3秒执行一次)
scheduler.scheduleAtFixedRate(() -> {
System.out.println("[" + getCurrentTime() + "] 固定频率任务执行");
}, 0, 3, TimeUnit.SECONDS);
// 3. 固定延迟执行(上次执行完后2秒再执行)
scheduler.scheduleWithFixedDelay(() -> {
try {
Thread.sleep(2000); // 模拟任务执行耗时
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("[" + getCurrentTime() + "] 固定延迟任务执行");
}, 0, 2, TimeUnit.SECONDS);
// 设置定时关闭(演示用,实际项目中根据需要)
scheduler.schedule(() -> {
System.out.println("调度器关闭");
scheduler.shutdown();
}, 20, TimeUnit.SECONDS);
}
private static String getCurrentTime() {
return LocalDateTime.now().format(FORMATTER);
}
}
使用 Timer 和 TimerTask
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimerExample {
public static void main(String[] args) throws InterruptedException {
Timer timer = new Timer("MyTimer");
// 1. 立即执行,然后每2秒执行一次
timer.schedule(new SimpleTask("任务A"), 0, 2000);
// 2. 延迟3秒执行一次
timer.schedule(new SimpleTask("任务B"), 3000);
// 3. 指定时间执行
Date scheduledTime = new Date(System.currentTimeMillis() + 5000);
timer.schedule(new SimpleTask("任务C"), scheduledTime);
// 4. 演示取消任务
TimerTask cancelTask = new SimpleTask("将被取消的任务");
timer.schedule(cancelTask, 1000, 1000);
// 5秒后取消指定任务
Thread.sleep(5000);
cancelTask.cancel();
System.out.println("已取消任务");
// 10秒后取消所有任务
Thread.sleep(5000);
timer.cancel();
System.out.println("所有任务已取消");
}
static class SimpleTask extends TimerTask {
private final String taskName;
public SimpleTask(String taskName) {
this.taskName = taskName;
}
@Override
public void run() {
System.out.println("[" + new Date() + "] " + taskName + " 执行时间:" +
new java.text.SimpleDateFormat("HH:mm:ss").format(new Date()));
}
}
}
使用 Quartz 框架
1 Maven依赖
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
2 完整的Quartz实现
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class QuartzExample {
private static final DateTimeFormatter FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 定义一个Job类
public static class MyJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
String jobName = dataMap.getString("jobName");
System.out.println("[" + LocalDateTime.now().format(FORMATTER) +
"] 任务[" + jobName + "]执行,线程:" + Thread.currentThread().getName());
}
}
public static void main(String[] args) {
try {
// 创建调度器
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// 1. 简单触发器 - 每3秒执行一次
JobDetail simpleJob = JobBuilder.newJob(MyJob.class)
.withIdentity("simpleJob", "group1")
.usingJobData("jobName", "简单任务")
.build();
SimpleTrigger simpleTrigger = TriggerBuilder.newTrigger()
.withIdentity("simpleTrigger", "group1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(3)
.repeatForever())
.build();
scheduler.scheduleJob(simpleJob, simpleTrigger);
// 2. Cron触发器 - 每天的特定时间执行
JobDetail cronJob = JobBuilder.newJob(MyJob.class)
.withIdentity("cronJob", "group2")
.usingJobData("jobName", "CRON任务")
.build();
// Cron表达式:秒 分 时 日 月 周
// 这里设置每30秒执行一次
CronTrigger cronTrigger = TriggerBuilder.newTrigger()
.withIdentity("cronTrigger", "group2")
.withSchedule(CronScheduleBuilder.cronSchedule("0/30 * * * * ?"))
.build();
scheduler.scheduleJob(cronJob, cronTrigger);
// 启动调度器
scheduler.start();
// 演示5秒后暂停某个Job
Thread.sleep(5000);
System.out.println("暂停simpleJob");
scheduler.pauseJob(JobKey.jobKey("simpleJob", "group1"));
// 再过3秒恢复
Thread.sleep(3000);
System.out.println("恢复simpleJob");
scheduler.resumeJob(JobKey.jobKey("simpleJob", "group1"));
// 运行15秒后关闭
Thread.sleep(15000);
scheduler.shutdown();
System.out.println("调度器已关闭");
} catch (SchedulerException | InterruptedException e) {
e.printStackTrace();
}
}
}
使用 Spring 的 @Scheduled 注解(Spring Boot)
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@SpringBootApplication
@EnableScheduling // 启用定时任务
public class SpringBootSchedulerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootSchedulerApplication.class, args);
}
}
@Component
class ScheduledTasks {
private final org.slf4j.Logger logger =
org.slf4j.LoggerFactory.getLogger(ScheduledTasks.class);
// 固定延迟 - 上一次执行完3秒后执行
@Scheduled(fixedDelay = 3000)
public void fixedDelayTask() {
logger.info("固定延迟任务执行: {}", System.currentTimeMillis());
try {
Thread.sleep(1000); // 模拟任务耗时
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
// 固定频率 - 每2秒执行一次(并行执行)
@Scheduled(fixedRate = 2000)
public void fixedRateTask() {
logger.info("固定频率任务执行: {}", System.currentTimeMillis());
}
// 初始延迟5秒后,每4秒执行一次
@Scheduled(initialDelay = 5000, fixedRate = 4000)
public void initialDelayTask() {
logger.info("带初始延迟的任务执行: {}", System.currentTimeMillis());
}
// Cron表达式任务 - 每天中午12点执行
@Scheduled(cron = "0 0 12 * * ?")
public void cronTask() {
logger.info("每天中午12点执行的任务");
}
// Cron表达式 - 每小时的15分、30分执行
@Scheduled(cron = "0 15,30 * * * ?")
public void multipleTimesTask() {
logger.info("每小时15分和30分执行的任务");
}
// Cron表达式 - 工作日早上9点执行
@Scheduled(cron = "0 0 9 ? * MON-FRI")
public void workdayTask() {
logger.info("工作日早上9点执行的任务");
}
// Cron表达式 - 每月1号零点执行
@Scheduled(cron = "0 0 0 1 * ?")
public void monthlyTask() {
logger.info("每月1号执行的任务");
}
}
生产环境定时任务管理器
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 生产环境定时任务管理器
*/
public class TaskSchedulerManager {
// 调度线程池
private final ScheduledExecutorService scheduler;
// 监控线程池
private final ConcurrentHashMap<String, TaskInfo> taskRegistry = new ConcurrentHashMap<>();
// 任务执行计数器
private final AtomicInteger taskCounter = new AtomicInteger(0);
private static final DateTimeFormatter FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public TaskSchedulerManager() {
// 创建固定大小的调度线程池
this.scheduler = Executors.newScheduledThreadPool(4, r -> {
Thread thread = new Thread(r, "schedule-worker");
thread.setUncaughtExceptionHandler((t, e) ->
System.out.println("[" + getCurrentTime() + "] 线程异常: " + e.getMessage()));
return thread;
});
}
/**
* 任务信息
*/
public static class TaskInfo {
private final String taskId;
private final String taskName;
private final ScheduledFuture<?> future;
private final Long executeCount;
private Throwable lastError;
public TaskInfo(String taskId, String taskName, ScheduledFuture<?> future) {
this.taskId = taskId;
this.taskName = taskName;
this.future = future;
this.executeCount = 0L;
}
public String getTaskId() { return taskId; }
public String getTaskName() { return taskName; }
public ScheduledFuture<?> getFuture() { return future; }
public Long getExecuteCount() { return executeCount; }
public boolean isCancelled() {
return future.isCancelled();
}
public boolean isDone() {
return future.isDone();
}
}
/**
* 注册固定频率任务
*/
public TaskInfo scheduleAtFixedRate(String taskId, String taskName,
Runnable task, long initialDelay, long period) {
try {
ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(() -> {
try {
taskCounter.incrementAndGet();
System.out.println("[" + getCurrentTime() + "] " + taskName + " 开始执行");
task.run();
System.out.println("[" + getCurrentTime() + "] " + taskName + " 执行完成");
} catch (Exception e) {
System.err.println("[" + getCurrentTime() + "] " + taskName + " 执行异常: " + e.getMessage());
}
}, initialDelay, period, TimeUnit.SECONDS);
TaskInfo taskInfo = new TaskInfo(taskId, taskName, future);
taskRegistry.put(taskId, taskInfo);
System.out.println("[" + getCurrentTime() + "] 注册固定频率任务: " + taskName);
return taskInfo;
} catch (Exception e) {
System.err.println("注册任务失败: " + e.getMessage());
throw new RuntimeException("任务注册失败", e);
}
}
/**
* 注册一次性延迟任务
*/
public TaskInfo scheduleOneTime(String taskId, String taskName,
Runnable task, long delay) {
ScheduledFuture<?> future = scheduler.schedule(() -> {
try {
taskCounter.incrementAndGet();
System.out.println("[" + getCurrentTime() + "] " + taskName + " 开始执行(一次性)");
task.run();
System.out.println("[" + getCurrentTime() + "] " + taskName + " 执行完成(一次性)");
} catch (Exception e) {
System.err.println("[" + getCurrentTime() + "] " + taskName + " 执行异常: " + e.getMessage());
}
}, delay, TimeUnit.SECONDS);
TaskInfo taskInfo = new TaskInfo(taskId, taskName, future);
taskRegistry.put(taskId, taskInfo);
System.out.println("[" + getCurrentTime() + "] 注册一次性任务: " + taskName);
return taskInfo;
}
/**
* 取消任务
*/
public boolean cancelTask(String taskId, boolean mayInterruptIfRunning) {
TaskInfo taskInfo = taskRegistry.get(taskId);
if (taskInfo != null && taskInfo.getFuture() != null) {
boolean cancelled = taskInfo.getFuture().cancel(mayInterruptIfRunning);
if (cancelled) {
System.out.println("[" + getCurrentTime() + "] 任务取消成功: " + taskInfo.getTaskName());
taskRegistry.remove(taskId);
}
return cancelled;
}
return false;
}
/**
* 获取所有任务状态
*/
public void printTaskStatus() {
System.out.println("========== 任务状态 ==========");
taskRegistry.forEach((taskId, taskInfo) -> {
System.out.println("任务ID: " + taskId +
", 名称: " + taskInfo.getTaskName() +
", 状态: " + (taskInfo.isCancelled() ? "已取消" :
taskInfo.isDone() ? "已完成" : "运行中"));
});
System.out.println("总执行次数: " + taskCounter.get());
System.out.println("================================");
}
/**
* 关闭调度器
*/
public void shutdown() {
System.out.println("[" + getCurrentTime() + "] 开始关闭调度器...");
scheduler.shutdown();
try {
if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
scheduler.shutdownNow();
}
System.out.println("[" + getCurrentTime() + "] 调度器已关闭");
} catch (InterruptedException e) {
scheduler.shutdownNow();
Thread.currentThread().interrupt();
}
}
private static String getCurrentTime() {
return LocalDateTime.now().format(FORMATTER);
}
// 测试主方法
public static void main(String[] args) throws InterruptedException {
TaskSchedulerManager manager = new TaskSchedulerManager();
// 注册各种任务
manager.scheduleAtFixedRate("task1", "数据备份任务", () -> {
System.out.println("备份数据到远程服务器...");
}, 0, 5);
manager.scheduleAtFixedRate("task2", "日志清理任务", () -> {
System.out.println("清理过期日志文件...");
}, 2, 10);
manager.scheduleOneTime("task3", "系统维护任务", () -> {
System.out.println("执行系统维护...");
}, 8);
// 模拟运行环境
Thread.sleep(15000);
// 查看任务状态
manager.printTaskStatus();
// 取消某个任务
manager.cancelTask("task2", true);
// 关闭调度器
Thread.sleep(5000);
manager.shutdown();
}
}
常用CRON表达式示例
public class CronExamples {
/*
* 常用CRON表达式示例(Quartz格式):
*
* "0 0 12 * * ?" - 每天中午12点执行
* "0 15 10 ? * *" - 每天10:15执行
* "0 15 10 * * ?" - 每天10:15执行
* "0 0/5 14,18 * * ?" - 每天14点和18点的0分、5分、10分...
* "0 15 10 ? * MON-FRI" - 周一至周五10:15执行
* "0 15 10 15 * ?" - 每月15日10:15执行
* "0 0 2 1 * ?" - 每月1日凌晨2点执行
* "0 0 0 ? * MON" - 每周一零点执行
* "0 0 0 1 1 ?" - 每年1月1日零点执行
*
* 字段含义:
* 位置1: 秒 (0-59)
* 位置2: 分 (0-59)
* 位置3: 时 (0-23)
* 位置4: 日 (1-31)
* 位置5: 月 (1-12 或 JAN-DEC)
* 位置6: 周 (1-7 或 SUN-SAT)
* 位置7: 年(可选) (1970-2099)
*
* 特殊字符:
* * : 所有值
* ? : 不指定值(仅用于日/周)
* - : 范围
* , : 列表
* / : 步长
*/
}
选择建议
- 简单任务:使用
ScheduledExecutorService(轻量级、可靠) - 复杂调度:使用 Quartz(支持复杂的CRON表达式、持久化、集群)
- Spring项目:使用
@Scheduled注解(简单快捷) - 分布式场景:使用 Quartz集群或其他分布式调度框架
这个案例涵盖了Java中主要的定时任务调度方式,你可以根据实际需求选择合适的方式。