Skip to content

前言

定时任务允许我们自动化处理、数据备份、资源清理等操作,提高系统的稳定性和可靠性。

  • 定时备份数据库
  • 每天发送项目切面数据邮件
  • 定时刷新页面缓存
  • 延时关单失败的数据兜底处理

快速开始

下面将介绍 Java 中三种常见的定时任务实现方式。

Java Timer

java.util.Timer 适用于简单的定时任务需求。由于 Timer 是单线程会造成任务阻塞,并且单个任务执行异常会造成整个定时任务终止执行。

java
Timer timer = new Timer();
timer.schedule(new TimerTask() {
  @Override
  public void run() {
    System.out.println("hello world");
  }
}, 0, 1000);

说明下后两个参数分别是delay延迟执行,和period执行间隔,单位都是毫秒。

ScheduledThreadPoolExecutor

java
ScheduledExecutorService service = Executors.newScheduledThreadPool(64);
service.scheduleAtFixedRate(() -> System.out.println("hello world"), 0, 1, TimeUnit.SECONDS);

相比于 TimerScheduledThreadPoolExecutor 基于线程池可以更好地控制并发性,并且任务之间也互不影响。

Spring @Scheduled

通过 @Scheduled 注解,你可以在 Spring 容器中非常简单地配置定时任务。既能定时任务代码与业务逻辑更加紧密集成,又能享受 Spring 提供的便捷特性。

注:需要手动打开 @EnableScheduling 标识。

java
@Slf4j
@Component
public class MyScheduledTasks {

    @Scheduled(fixedDelay = 5000) // 间隔5秒执行一次
    public void task1() {
        log.info("任务 task1 执行...");
        // 执行任务逻辑
    }

    @Scheduled(fixedRate = 10000) // 每隔10秒执行一次
    public void task2() {
        log.info("任务 task2 执行...");
        // 执行任务逻辑
    }
}
  • fixedDelay:上一次任务执行完成后到下一次任务开始执行的时间间隔。
  • fixedRate:上一次任务开始执行后到下一次任务开始执行的时间间隔。

第三方组件

传统的 Quartz,当下流行的 xxl-job 等等。技术选型时,需要结合当前业务的具体情况。

常见问题

分布式多次执行

  1. 增加任务执行分布式锁,保证单节点执行;
  2. 使用数据库全局任务执行状态,只有一个节点能修改该标记位;
  3. 引入分布式调度中心,例如 xxl-job;

根据项目具体需求、技术栈和复杂度来选择最合适的方法。

执行时间超过间隔时间

  1. 任务异步执行,实际执行时间不影响后续任务调度;
  2. 采用固定延迟策略,例如 fixedDelay 直至上个任务执行完成;

基于 MIT 许可发布