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());
}