赞
踩
aop和redis POM添加:
- <!--redis驱动-->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-redis</artifactId>
- </dependency>
-
- <!--aop面向切面编程-->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-aop</artifactId>
- </dependency>
自定义分布式定时任务注解
- /**
- * @program:
- * @description: 定时任务锁
- * @author: wangZhiDong
- * @created: 2021/11/29 09:06
- */
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- public @interface TaskLock {
-
- /**
- * 定时任务名称
- * @return
- */
- String name() default "";
-
- /**
- * redis缓存key值
- * @return
- */
- String key();
-
- /**
- * 过期时间单位s (自动解锁时间,防止死锁)
- * @return
- */
- int expired();
-
- /**
- * 执行完毕是否解锁
- * @return
- */
- boolean unLock() default true;
-
-
- }
定义 分布式定时任务 切面具体实现
- /**
- * @program:
- * @description: 定时任务锁切面
- * @author: wangZhiDong
- * @created: 2021/10/29 09:12
- */
- @Aspect
- @Component
- @Slf4j
- @AllArgsConstructor
- @Order(10)
- public class TaskLockAspect {
-
- private RedisTemplate redisTemplate;
-
- @Pointcut("@annotation(com.wang.timedtask.annotation.TaskLock)")
- public void TaskLockAspect() {
-
- }
-
-
- @Around("TaskLockAspect() && @annotation(taskLock)")
- public Object doAround(ProceedingJoinPoint proceedingJoinPoint,TaskLock taskLock) throws Throwable {
- String value = UUID.randomUUID().toString();
- try {
- if (lock(taskLock.key(), value, taskLock.expired())) {
- return proceedingJoinPoint.proceed();
- }
- } catch (Exception e) {
- log.error("定时任务执行失败,{}", taskLock.key(), e);
- } finally {
- // 执行完毕解除锁
- if (!taskLock.unLock()) {
- return null;
- }
- String lockValue = getLockValue(taskLock.key());
- if (StringUtils.isEmpty(lockValue) || !lockValue.equals(value)) {
- return null;
- }
- // 解锁设置为延时1S
- unLock(taskLock.key());
- }
- return null;
- }
-
-
-
- /**
- * 加锁
- * @param key
- * @param value
- * @param time
- * @return
- */
- public boolean lock(String key , String value , int time){
- return redisTemplate.opsForValue().setIfAbsent(key , value , time , TimeUnit.SECONDS);
- }
-
-
- /**
- * 解锁
- * @param key
- */
- public void unLock(String key){
- redisTemplate.expire(key , 1 , TimeUnit.SECONDS);
- }
-
- /**
- * 获取锁值
- * @param key
- * @return
- */
- public String getLockValue(String key){
- return (String) redisTemplate.opsForValue().get(key);
- }
- }
简单使用
- /**
- * @Author wangZhiDong
- * @Date 2021/8/22
- * 启动数据纠正
- **/
- @Slf4j
- @Component
- public class TransferService {
-
- public static int num = 0;
- DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
-
- @Scheduled(cron = "0/5 * * * * ?")
- @TaskLock(name = "测试分布式定时任务5秒执行一次", key = "test_task",expired = 5)
- public void start(){
- num++;
- System.out.println(LocalDateTime.now().format(formatter)+"第"+num+"次执行的是第一个");
- }
-
- /**
- * 使用 public 的 定时任务才行
- */
- @Scheduled(cron = "0/5 * * * * ?")
- @TaskLock(name = "测试分布式定时任务5秒执行一次", key = "test_task",expired = 5)
- public void start2(){
- TransferService.num++;
- System.out.println(LocalDateTime.now().format(formatter)+"第"+TransferService.num+"次执行的是第二个");
- }
-
- @Scheduled(cron = "0/5 * * * * ?")
- @TaskLock(name = "测试分布式定时任务5秒执行一次", key = "test_task",expired = 5)
- public void start3(){
- TransferService.num++;
- System.out.println(LocalDateTime.now().format(formatter)+"第"+TransferService.num+"次执行的是第三个");
- }
-
-
- }
执行结果:
2021-12-01 14:35:40第1次执行的是第一个
2021-12-01 14:35:45第2次执行的是第二个
2021-12-01 14:35:50第3次执行的是第三个
2021-12-01 14:35:55第4次执行的是第三个
2021-12-01 14:36:00第5次执行的是第二个
2021-12-01 14:36:05第6次执行的是第一个
2021-12-01 14:36:10第7次执行的是第三个
2021-12-01 14:36:15第8次执行的是第一个
2021-12-01 14:36:20第9次执行的是第二个
2021-12-01 14:36:25第10次执行的是第三个
2021-12-01 14:36:30第11次执行的是第一个
...
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。