阅读量:4
1.定位定时任务所走方法
打方法断点
随便找一个定时任务的方法类,打断点查看执行过程
执行方法
点击立即执行,执行该方法
定位方法
点击步过,寻找合适的代码位置增加分布式锁
最终看到方法在此处进行返回,我们可以再此处进行加锁操作
2.添加分布式锁
引入redisson依赖,添加配置类
在ruoyi-common pom引入redisson依赖
<!--Redisson redis若依已经引入--> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.17.4</version> </dependency>
添加配置类
package com.ruoyi.common.core.redis; import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @Author Cxt * @Description redisson配置 * @Date 2023/6/29 15:47 * @Version 1.0 */ @Configuration public class RedissonConfig { @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private String port; @Value("${spring.redis.password}") private String password; @Bean public RedissonClient redissonClient() { Config config = new Config(); // 配置Redisson连接信息 config.useSingleServer().setAddress("redis://" + host + ":" + port).setPassword(null); return Redisson.create(config); } }
引入redisson服务
如果开启了ScheduleConfig类 注入方式请改为如下图所示注入
修改原有的方法
在处理好sysJob对象后 根据任务名称来创建锁对象
@Override public void execute(JobExecutionContext context) throws JobExecutionException { SysJob sysJob = new SysJob(); BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES)); try { before(context, sysJob); if (sysJob != null) { //创建锁对象 RLock lock = redissonClient.getLock(ScheduleConstants.TASK_PROPERTIES); //尝试获取锁 boolean isLock = lock.tryLock(); if (!isLock){ throw new ServiceException("该任务正在执行中!"); } try{ //真正执行的方法 doExecute(context, sysJob); }finally { //释放锁 lock.unlock(); } } after(context, sysJob, null); } catch (Exception e) { log.error("任务执行异常 - :", e); after(context, sysJob, e); } }
3.测试
同一时间如果拿不到锁将会直接失败,成功达到效果
特别注意
在拿到锁之后,由于走的是本地缓存,为了避免重复执行,请将任务策略改为放弃执行
官方方法
取消注释类ScheduleConfig即可(注意查看相关表是否存在)