(资料图片仅供参考)
在此之前,去看了下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; }}
在此之前,去看了下Redission的实现原理,不过在开发中,原本的代码...
中新网4月21日电国家外汇管理局副局长、新闻发言人王春英21日表示,...
4月20日,华为宣布实现自主可控的MetaERP研发,并完成对旧ERP系统的...
“中年粉丝”能否创造奇迹?这场属于“湘北”的比赛才刚刚开始。
欧联杯1 4决赛次回合,曼联0-3不敌塞维利亚,总比分2-5被淘汰,马...
为子女教育而想落户上海的父母,注意有这四种情况
“您认真负责、办事公正使我们记忆深刻这些年里每每想起此事总会想...
三湘都市报·新湖南客户端4月20日讯(全媒体记者潘显璇)今天,由中...
20年前,远程医疗、机器人医生或3D打印器官还被认为是科幻小说的情...
今天来聊聊关于中涓自此榆横,中涓的文章,现在就为大家来简单介绍...
五一小长假陪娃出游,带上这份安全攻略!
每棵玉米,在他眼里都有鲜活的生命——记2023年度河北大工匠、邯郸...
近日,网飞新纪录片《非洲女王:克利奥帕特拉女王》中,采用黑人演...
昨日,溪东路静待通车。(本报记者王协云摄)长1 38公里、跨越南港...
4月20日上午,猪肉股逆势走高,新五丰涨超3%,巨星农牧、温氏股份小...
武汉江夏:生态修复让灵山复绿“重生”
高性能取向电工钢专业化生产线在河北迁安投产
4月21日,生意社角钢基准价为3936 67元 吨,与本月初(4013 33元...
湖人助教疑讽狄龙:不要责怪小丑问问你自己为什么去马戏团,狄龙,湖...
直播吧4月20日讯踢球者消息,沃尔夫斯堡正寻求左后卫的补强,他们有...
大公网港股频道
1、wuli是韩语。2、中文是我们的意思。3、狗带=godie 翻译过来就是...
共计1200余套!顺义又一处回迁房月底前交房!,交房,顺义,户型,样板...
安徽宿州乡村,一个女杂技演员在表演时从高空坠落,不治身亡,这被...
证券时报e公司讯,隆华新材(301149)4月19日晚间公告,公司拟在山东...
迪亚兹占据领先之后,国乒主帅马琳坐不住了,十分担心王艺迪重蹈陈...
强对流天气:目前是指伴随雷暴现象的对流性大风(≥17 2m s)、冰...
4月17日,高桥石化首座分布式光伏发电设施正式投用并网发电,标志着...
一季度城镇调查失业率:16-24岁失业率为19 6%“就业形势总体稳定,...
中国人民银行今天(20日)在一季度金融统计数据新闻发布会上,针对...