【资料图】
在此之前,去看了下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的实现原理,不过在开发中,原本的代码...
女孩骑车蹭花私家车,家长却称只赔20元,车主:划痕有5厘米,他说如...
文|徐大志图|池俊成、刘志勇、刘思宇、张笑领、王小杰、刘声水润万...
据介绍,盐源风电项目的5兆瓦机型风机叶片单只重量为22 5吨,长度...
承德露露(000848)04月21日在投资者关系平台上答复了投资者关心的问题。
促进数字经济产业发展,这场论坛干货满满
4月22日9:30,大庆市图书馆“艺术工坊”举办藏书票制作活动,地点...
风起洛阳北京卫视上星 北京卫视风起洛阳 神都闹饥荒,民众聚...
近年来,在互联网上进行线上医疗咨询为很多人的生活提供了便利,但...
衣服越买越多,但是衣柜空间是不变的。怎样使这些衣服都整齐地放在...
今天小编肥嘟来为大家解答以上的问题。坐围和臀围有什么区别,坐围...
南方网讯(记者 柯丹洁)近日,2023年广州高企高质量发展对接会—...
3月以来,有网友从杭州市政府网上发现了一批行政处罚的公开信息,内...
1、Unit1:Young(年轻的)5261funny(滑稽可笑的4102)tall(高的)stron
CQF考试是金融领域内的一项专业考试,是金融领域内的一项专业认证,...
近日卓创资讯披露,截至2023年3月31日公司股东户数为5707 0户,较2...
2023年4月19日,第18届SIUF中国(深圳)国际品牌内衣展暨中国内衣文化...
观察|美轰炸机首现中印边境地区参加演习,意欲为何?,战机,空军,演...
一、内蒙古自治区呼和浩特市天气预报1、呼和浩特市气象台2023年04月...
□盛杨阳(西京学院)人为什么有两只眼睛却只有一张嘴?为什么没有...
空砍10+7+4!李凯尔无缘导演逆转,安抚暴怒的戈贝尔,黑八悬了,黑八...
橙柿互动报道这两天,广西柳州柳江的一则视频火了,视频中,菜场一...
你们好,最近小活发现有诸多的小伙伴们对于笔记本电脑自动修复失败...
1、智齿导致牙龈肿痛的情况是比较常见的,相信不少朋友都遇到过,一...
三维天地荣获2023年“中国轻工业数字化转型战略合作伙伴” 4月...
现如今CBA联赛季后赛激战正酣,但山东男篮这边因为惨遭广州龙狮横扫...
中国联通(00762)发布公告,截至2023年3月份,“大联接”用户累计...
对于预算不高的朋友来说,买一部性价比高的手机才最合适,有些手机...
欧洲央行管委维斯科:做得太多的风险至少与做得太少的风险一样大
读创 深圳商报首席记者王海荣日前,深圳市科创委对2023年度可持续...