SpringTask

Spring Task 是 Spring 框架提供的任务调度工具,可帮助开发者方便地创建定时执行的任务。

1. 基础使用:基于注解的简单定时任务

步骤 1:启用定时任务支持

在 Spring Boot 主类或配置类上添加@EnableScheduling注解。

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);
    }
}
步骤 2:创建定时任务 Bean

使用@Scheduled注解标记方法,指定执行周期。

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class MyScheduledTasks {

    // 每5秒执行一次(fixedRate:上次任务开始后5秒执行下一次)
    @Scheduled(fixedRate = 5000)
    public void fixedRateTask() {
        System.out.println("Fixed Rate Task executed at: " + System.currentTimeMillis());
    }

    // 上次任务结束后延迟3秒执行下一次
    @Scheduled(fixedDelay = 3000)
    public void fixedDelayTask() {
        System.out.println("Fixed Delay Task executed at: " + System.currentTimeMillis());
    }

    // 初始延迟1秒后开始,之后每2秒执行一次
    @Scheduled(initialDelay = 1000, fixedRate = 2000)
    public void initialDelayTask() {
        System.out.println("Initial Delay Task executed at: " + System.currentTimeMillis());
    }

    // 使用Cron表达式:每天早上8点执行
    @Scheduled(cron = "0 0 8 * * ?")
    public void cronTask() {
        System.out.println("Cron Task executed at 8:00 AM daily");
    }
}

2. Cron 表达式进阶

Cron 表达式由 6 或 7 个字段组成,依次为:秒 分 时 日 月 周 [年]

常用示例
表达式说明
0 0 12 * * ?每天中午 12 点执行
0 15 10 * * ?每天上午 10:15 执行
0 0/5 14 * * ?每天下午 2 点到 2:55 每 5 分钟执行
0 0 12 ? * WED每周三中午 12 点执行
0 0 0/1 * * ?每小时执行一次

3. 异步执行定时任务

默认情况下,所有定时任务在同一个线程中串行执行。若需并行执行,可配置异步支持:

步骤 1:启用异步支持
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;

@Configuration
@EnableAsync // 启用异步支持
public class AsyncConfig {
    // 可自定义线程池配置(可选)
}
步骤 2:标记任务为异步
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class AsyncTasks {

    @Async // 异步执行
    @Scheduled(fixedRate = 5000)
    public void asyncTask() throws InterruptedException {
        System.out.println("Async Task started at: " + System.currentTimeMillis());
        Thread.sleep(2000); // 模拟耗时操作
        System.out.println("Async Task finished at: " + System.currentTimeMillis());
    }
}

4. 动态定时任务(高级)

通过实现SchedulingConfigurer接口,可动态调整任务执行周期。

示例:动态调整 Cron 表达式
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

@Configuration
@EnableScheduling
public class DynamicSchedulingConfig implements SchedulingConfigurer {

    private String cronExpression = "0/5 * * * * ?"; // 初始每5秒执行一次

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(
            () -> System.out.println("Dynamic Task executed at: " + System.currentTimeMillis()),
            triggerContext -> {
                // 动态获取Cron表达式(可从数据库、配置中心获取)
                return new CronTrigger(cronExpression).nextExecutionTime(triggerContext);
            }
        );
    }

    // 自定义线程池
    @Bean(destroyMethod="shutdown")
    public Executor taskExecutor() {
        return Executors.newScheduledThreadPool(5);
    }

    // 动态修改Cron表达式的方法
    public void updateCronExpression(String newExpression) {
        this.cronExpression = newExpression;
        System.out.println("Cron表达式已更新为: " + newExpression);
    }
}

5. 错误处理与监控

统一异常处理
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(25);
        executor.setThreadNamePrefix("MyAsyncTask-");
        executor.setRejectedExecutionHandler((r, executor1) -> {
            System.err.println("任务队列已满,拒绝执行: " + r.toString());
        });
        executor.initialize();
        return executor;
    }

    // 统一异常处理
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (ex, method, params) -> {
            System.err.println("异步任务执行异常: " + ex.getMessage());
            ex.printStackTrace();
        };
    }
}

6. 分布式环境下的任务调度

在分布式系统中,需避免多节点重复执行同一任务。可使用以下方案:

  • Redis 锁:通过 Redis 的原子操作实现任务互斥。
  • 分布式任务调度框架:如 Elastic-Job、xxl-job、Quartz 集群。
示例:基于 Redis 实现分布式锁
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
public class DistributedTask {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final String LOCK_KEY = "task:distributed_lock";
    private static final long LOCK_TIMEOUT = 30; // 锁超时时间(秒)

    @Scheduled(fixedRate = 60000) // 每分钟执行一次
    public void distributedTask() {
        Boolean locked = redisTemplate.opsForValue().setIfAbsent(LOCK_KEY, "locked", LOCK_TIMEOUT, TimeUnit.SECONDS);
        if (locked != null && locked) {
            try {
                // 获取到锁,执行任务
                System.out.println("分布式任务执行中...");
                // 业务逻辑...
            } finally {
                // 释放锁
                redisTemplate.delete(LOCK_KEY);
            }
        } else {
            System.out.println("其他节点正在执行任务,当前节点跳过");
        }
    }
}

总结

  1. 基础:使用@EnableScheduling@Scheduled实现简单定时任务。
  2. Cron 表达式:灵活控制任务执行时间。
  3. 异步执行:通过@Async实现任务并行。
  4. 动态调整:实现SchedulingConfigurer接口动态修改执行周期。
  5. 分布式场景:使用 Redis 锁或专业框架避免任务重复执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值