SchedulerLock分布式定时任务锁

1.pom中引入依赖,这里使用redis作为锁

复制代码
        <dependency>
            <groupId>net.javacrumbs.shedlock</groupId>
            <artifactId>shedlock-spring</artifactId>
            <version>4.12.0</version>
        </dependency>
        <dependency>
            <groupId>net.javacrumbs.shedlock</groupId>
            <artifactId>shedlock-provider-redis-spring</artifactId>
            <version>4.12.0</version>
        </dependency>

2.yml配置redis连接

复制代码
spring:
 redis:
    host: localhost
    port: 6379
    database: 0
    taskrelease: taskrelease

3.配置redis序列化

复制代码
@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        // 使用Jackson2JsonRedisSerialize 替换默认序列化
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        // 设置value的序列化规则和 key的序列化规则
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

4.线程池和分布式锁配置

复制代码
import lombok.extern.slf4j.Slf4j;
import net.javacrumbs.shedlock.core.LockProvider;
import net.javacrumbs.shedlock.provider.redis.spring.RedisLockProvider;
import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

import javax.annotation.Resource;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
@EnableSchedulerLock(defaultLockAtMostFor = "PT30M")
@Slf4j
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {

    @Resource
    ExecutorService scheduledThreadPoolExecutor;

    /**
     *
     */
    @Bean
    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //最大线程数
        executor.setMaxPoolSize(8);
        //核心线程数
        executor.setCorePoolSize(8);
        //任务队列的大小
        executor.setQueueCapacity(100);
        //线程前缀名
        executor.setThreadNamePrefix("common-");
        //线程存活时间
        executor.setKeepAliveSeconds(30);
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        //线程初始化
        executor.initialize();
        return executor;
    }

    /**
     * 动态调度任务线程池
     */
    @Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
        // 线程池大学
        threadPoolTaskScheduler.setPoolSize(15);
        // 线程名称
        threadPoolTaskScheduler.setThreadNamePrefix("taskScheduler-");
        // 等待时长
        threadPoolTaskScheduler.setAwaitTerminationSeconds(60);
        // 调度器shutdown被调用时等待当前被调度的任务完成
        threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true);
        return threadPoolTaskScheduler;
    }

    /**
     * Schedule定时任务指定线程池
     * Spring注解
     */
    @Bean(name = "scheduledThreadPoolExecutor")
    public ScheduledThreadPoolExecutor scheduledThreadPoolExecutor() {
        return new ScheduledThreadPoolExecutor(15);
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        //显式为Scheduler指定线程池
        taskRegistrar.setScheduler(scheduledThreadPoolExecutor);
    }

    /**
     * 分布式锁
     * Schedule定时任务, Spring注解
     */
    @Bean
    public LockProvider lockProvider(RedisConnectionFactory connectionFactory) {
        return new RedisLockProvider(connectionFactory, System.getProperty("spring.profiles.active"));
    }
}

5.执行任务方法

复制代码
    @Scheduled(cron = "0 0 23 * * ?")
    @SchedulerLock(name = "synchronizeAddDept", lockAtLeastFor = "PT15S")
    public void synchronizeAddDept() {
        StopWatch watch = new StopWatch();
        watch.start();
        log.info("====================> 同步部门数据开始, {}", LocalDateTime.now());
        watch.stop();
        log.info("====================> 同步部门数据结束, {}, 用时 {}", LocalDateTime.now(), 
        watch.getTotalTimeSeconds());
}
相关推荐
lantian1 分钟前
TypeScript 模块系统核心原理:从ESM到CJS,彻底搞懂模块格式与解析逻辑
前端·typescript·ecmascript 6
一只积极向上的小咸鱼2 分钟前
TOML、JSON、YAML、INI 配置文件格式总结
java·服务器·json
Lear3 分钟前
CSR、SSR、SSG 到底怎么选?一文讲透现代前端三大渲染模式
前端
莫逸风4 分钟前
【AgentScope】4.会话(Session)详解
java·llm·agent·agentscope
এ慕ོ冬℘゜8 分钟前
前端分页组件完整实现:样式 + 交互 + 逻辑全优化
前端·交互
Ajie'Blog11 分钟前
Claude Opus 4.8 发布:Claude Code 能不能接住复杂项目
服务器·前端·javascript·人工智能·ai编程
2501_9181269112 分钟前
火柴人踢任意球
javascript·css·css3
吴阿福|一人公司13 分钟前
类变量和实例变量的命名规范有哪些具体的例子?
java·开发语言
eddietao15 分钟前
什么是 fail-fast?什么是 fail-safe?
java·面试
San813_LDD15 分钟前
[后端开发]GET/POST_带参/不带参
前端·后端·计算机网络·json