(资料图片)
在此之前,去看了下Redission的实现原理,不过在开发中,原本的代码使用RedistTemplate实现的,也不太想换,所以我想了下,不如自己实现要给WatchDog。
我的想法是,在用户加上锁的时候开启个定时任务线程,并且在定时任务中,判断原线程isAlive状态进行“续命”。
下面是代码(在这里面为了方便,未使用的是HuTool.CornUtil来实现动态定时任务):
/** * Title * * @ClassName: LockUtil * @Description:锁工具类,通过内部枚举类实现单例,防止反射攻击 * @author: Karos * @date: 2023/1/4 0:17 * @Blog: https://www.wzl1.top/ */package cn.katool.lock;import cn.hutool.core.util.BooleanUtil;import cn.hutool.core.util.ObjectUtil;import cn.hutool.cron.CronUtil;import cn.hutool.cron.task.Task;import cn.katool.Config.LockConfig;import cn.katool.Exception.ErrorCode;import cn.katool.Exception.KaToolException;import cn.katool.other.MethodIntefaceUtil;import com.qiniu.util.StringUtils;import lombok.SneakyThrows;import lombok.extern.slf4j.Slf4j;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Scope;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.stereotype.Component;import org.springframework.util.ObjectUtils;import javax.annotation.Resource;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.TimeUnit;@Component@Scope("prototype")@Slf4jpublic class LockUtil { @Resource RedisTemplate redisTemplate; private LockUtil(){ } private static boolean isOpenCorn=false; /** * 带看门狗机制上锁 * @param lockObj * @return */ public boolean DistributedLock(Object lockObj){ try { return DistributedLock(lockObj,null,null); } catch (KaToolException e) { throw new RuntimeException(e); } } @Resource LockConfig lockConfig; //加锁 /** * 无看门狗机制上锁 * @param obj * @param exptime * @param timeUnit * @return * @throws KaToolException */ public boolean DistributedLock(Object obj,Long exptime,TimeUnit timeUnit) throws KaToolException { if (ObjectUtil.isEmpty(obj)){ throw new KaToolException(ErrorCode.PARAMS_ERROR," Lock=> 传入obj为空"); } Boolean isDelay=false; if (ObjectUtil.isAllEmpty(exptime,timeUnit)){ isDelay=true; } if(ObjectUtil.isEmpty(exptime)){ exptime= lockConfig.getInternalLockLeaseTime();; } if (ObjectUtils.isEmpty(timeUnit)){ timeUnit=lockConfig.getTimeUnit(); } //线程被锁住了,就一直等待 DistributedAssert(obj); Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("Lock:"+obj.toString(), "1", exptime, timeUnit); log.info("katool=> LockUntil => DistributedLock:{} value:{} extime:{} timeUnit:{}",obj.toString(), "1", exptime, timeUnit); //实现看门狗 if (isDelay){ if (LockUtil.isOpenCorn==false){ //如果同一个项目之前打开过,那么先关闭,避免重复启动 CronUtil.stop(); //支持秒级别定时任务 CronUtil.setMatchSecond(true); //定时服务启动 CronUtil.start(); LockUtil.isOpenCorn=true; } Thread thread = Thread.currentThread(); TimeUnit finalTimeUnit = timeUnit; Long finalExptime = exptime; class TempClass{ public String scheduleId; } final TempClass tempClass = new TempClass(); tempClass.scheduleId=CronUtil.schedule("0/30 * * * * ?", new Task() { @SneakyThrows @Override public void execute() { boolean alive = thread.isAlive(); if (alive) { delayDistributedLock(obj, finalExptime>=3?(finalExptime / 3):finalExptime, finalTimeUnit); return; } else { if (tempClass.scheduleId==null||"".equals(tempClass.scheduleId)){ return; } CronUtil.remove(tempClass.scheduleId); DistributedUnLock(obj); return; } } }); } return BooleanUtil.isTrue(aBoolean); } //检锁 public void DistributedAssert(Object obj) throws KaToolException { if (ObjectUtils.isEmpty(obj)){ throw new KaToolException(ErrorCode.PARAMS_ERROR," Lock=> 传入obj为空"); } while(true){ Object o = redisTemplate.opsForValue().get("Lock:" + obj.toString()); if (ObjectUtils.isEmpty(o))return; } } //延期 public boolean delayDistributedLock(Object obj,Long exptime,TimeUnit timeUnit) throws KaToolException { if (ObjectUtils.isEmpty(obj)){ throw new KaToolException(ErrorCode.PARAMS_ERROR," Lock=> 传入obj为空"); } Boolean aBoolean = redisTemplate.opsForValue().setIfPresent("Lock:"+obj.toString(), "1", exptime, timeUnit); log.info("katool=> LockUntil => delayDistributedLock:{} value:{} extime:{} timeUnit:{}",obj.toString(), "1", exptime, timeUnit); return BooleanUtil.isTrue(aBoolean); } //释放锁 public boolean DistributedUnLock(Object obj) throws KaToolException { if (ObjectUtils.isEmpty(obj)){ throw new KaToolException(ErrorCode.PARAMS_ERROR," Lock=> 传入obj为空"); } Boolean aBoolean = redisTemplate.delete("Lock:" + obj.toString()); log.info("katool=> LockUntil => unDistributedLock:{} isdelete:{} ",obj.toString(),true); return BooleanUtil.isTrue(aBoolean); } //利用枚举类实现单例模式,枚举类属性为静态的 private enum SingletonFactory{ Singleton; LockUtil lockUtil; private SingletonFactory(){ lockUtil=new LockUtil(); } public LockUtil getInstance(){ return lockUtil; } } @Bean("LockUtil") public static LockUtil getInstance(){ return SingletonFactory.Singleton.lockUtil; }}
X 关闭
- 1、每日报道:针对RedisTemplate分布式锁实现WatchDog
- 2、西城园协会央企小组丨【会员】央视市场研究:发布《2023年2月广告市场:波动与信号》报告 世界观速讯
- 3、香港知名女星看破红尘出家多年,罕见现身显沧桑,网友直呼不敢认|天天速读
- 4、“他们花钱让美国政客不作为!”
- 5、湘财股份(600095.SH):提请股东大会授权董事会以简易程序向特定对象发行股票|全球速看料
- 6、软银阿里分手,一个时代落幕
- 7、彬州喊我去看梨花,我却只想吃御面!西安出发高铁47分钟就到_全球视点
- 8、故宫东西六宫住哪些人 故宫东西六宫的相关介绍
- 9、2023年下半年中国将举办世界斯诺克巡回赛三项赛事
- 10、烟台黄渤海新区“圣文杯”美德信用公益宣传大赛正式启动 前沿热点
-
天天最新:英超形势:曼城VS阿森纳加把火 曼联笑看喜鹊热刺
英超争冠形势方面,由于曼城在本轮先赛1天,双方暂时算是拉平了场次,此前蓝月少赛1轮落后6分的局面变成了
-
中国驻苏丹使馆:尚未收到在苏中国公民伤亡报告_环球新视野
中国驻苏丹大使馆方面在接受总台采访时表示,冲突发生后使馆在第一时间启动应急响应机制,发布紧急安全提示
-
天天观速讯丨「大美中国」乐山乐水更乐业
【大美中国】光明日报记者周仕兴王瑾雯光明日报通讯员黄瑞玲与贵州省接壤的广西百色市西北部,有一个神奇秀
-
excel表格排序排不了怎么办_excel表格排序排不_环球速看
1、向各位高手请教excel表格排序不能按序排列了是由于设置错误,具体解决步骤如下:打开excel文档,将要排
-
秋乐种业:开拓海外市场折戟 “蒙眼”剔除同行或为装点竞争实力 环球新视野
2011年10月21日,河南秋乐种业科技股份有限公司(以下简称“秋乐种业”)以整体变更方式设立为股份公司。20
-
以定制化改性材料助推中国医疗行业自主创新,奥美凯与您相约CHINAPLAS 2023|天天精选
2023年4月17-20日,专注于开发、设计和生产定制色母粒、功能添加剂、改性工程塑料和高性能改性材料的全球聚
-
【世界快播报】三部门:对广交会展期内销售的进口展品免征进口关税、进口环节增值税和消费税
一、对2023年举办的广交会在商务部确定的展期内销售的免税额度内的进口展品免征进口关税、进口环节增值税和
-
全民国家安全教育日丨守护国家安全 我们可以做些什么?
4月15日是第八个全民国家安全教育日,今年的主题是“贯彻总体国家安全观,增强全民国家安全意识和素养,夯
-
新手开车最容易犯的四个错误,实习期注意提防,别成了大冤头_全球快报
新手开车经常会犯哪些错误?经常有新手司机跟喵哥提这个问题,让我跟大家讲一讲,我今天就给大家总结一下。
-
阵风7到8级!开封发布最新预警!_滚动
开封市气象台2023年4月15日8时41分继续发布大风蓝色预警信号:预计今天白天,龙亭区、顺河回族区、鼓楼区、