(相关资料图)
在此之前,去看了下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日电,立华股份公布2022年年度报告,2022年公司实现营业收入14...
第133届广交会4月15日起至5月5日在广州举办,首发首秀活动超300场,...
4月22日发布《恒生前海恒利纯债债券型证券投资基金分红公告》。本次...
Ñë¹ãÍø²©ÖÝ4ÔÂ22ÈÕÏûÏ¢£¨¼ûÏ°¼ÇÕß½ª...
1、一本好书是伴随人一生的财富,是照耀人一生的阳光,是带领人一生的...
4月21日,据英国《金融时报》,拜登周四在主要经济体能源和气候论坛...
格隆汇4月21日丨津上机床中国公布,公司董事会获公司控股股东Tsugam...
菠萝蜜通常高10至20米。树皮是深褐色,叶子是椭圆形的,花是雌雄同...
Damus等去中心化社交产品快速出圈又迅速沉寂,用户来过但又走了当拥...
据央视新闻,当地时间4月21日,德国铁路和运输工会召集德国全境铁路...
截至2022年10月19日收盘,万华化学(600309)报收于85 51元,下跌5 ...
电影《灌篮高手》出品公司的旗舰店,昨天也首发上线了10款《灌篮高...
1、在演技上,唐国强确实比艺鹭更胜一筹。2、但是,艺鹭真的把诸葛...
北京日报客户端|记者李瑶通讯员韩佳慧4月21日,红色革命老区——延...
李丽珍继《蜜桃成熟♦时》后的另一部作品,也是舒淇到香港后的...
1、自制苏打水是小苏打与凉开水或纯净水的混合物。取一小勺小苏打放...
记者21日从北京大学获悉,经过近20年努力,中国重大基础性学术文化...
解答:1、下载工行网银助手,请下载安装工行网银助手。该软件将指导...
1、如果九个月大的宝宝拉肚子,第一,新鲜的大便要装在干净的塑料容...
1、潭牛镇,隶属于海南省文昌市,地处文昌市中部,东与公坡镇、东阁...
4月21日,博时凤凰领航混合A最新单位净值为0 748元,累计净值为0 ...
中国日报网4月21日电4月21日,2023年中国网络媒体论坛“中国叙事?...
日前,车质网从相关渠道获悉,上汽大众朗逸(图片|配置|询价)1 5T车...
趋势巡航:三大原因引发大盘大跌今天大盘在科技股全线大跌的影响下,...
1、吃柚子不会减肥,但是对于减肥会起到一定的辅助作用。2、柚子是...
薛舒是一位小说家,她在《收获长篇小说2023春卷》上刊登的非虚构作...
南都电源(SZ300068,收盘价:20 47元)4月21日晚间发布公告称,20...
中新网4月20日电美国《国会山报》19日发布纽约市立大学公共卫生与卫...
1、要解决问题需要对症下药,找出问题所在,头发毛躁是因为头发水分...