Java实现定时任务调度案例

wen java案例 2

本文目录导读:

Java实现定时任务调度案例

  1. 使用 ScheduledExecutorService(推荐)
  2. 使用 Timer 和 TimerTask
  3. 使用 Quartz 框架
  4. 使用 Spring 的 @Scheduled 注解(Spring Boot)
  5. 生产环境定时任务管理器
  6. 常用CRON表达式示例
  7. 选择建议

我来提供一个完整的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)
     * 
     * 特殊字符:
     * * : 所有值
     * ? : 不指定值(仅用于日/周)
     * - : 范围
     * , : 列表
     * / : 步长
     */
}

选择建议

  1. 简单任务:使用 ScheduledExecutorService(轻量级、可靠)
  2. 复杂调度:使用 Quartz(支持复杂的CRON表达式、持久化、集群)
  3. Spring项目:使用 @Scheduled 注解(简单快捷)
  4. 分布式场景:使用 Quartz集群或其他分布式调度框架

这个案例涵盖了Java中主要的定时任务调度方式,你可以根据实际需求选择合适的方式。

上一篇Quartz案例

下一篇SpEL表达式案例

抱歉,评论功能暂时关闭!