最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用自定義注解實(shí)現(xiàn)redisson分布式鎖

 更新時(shí)間:2022年02月17日 11:31:28   作者:SillinessPlus  
這篇文章主要介紹了使用自定義注解實(shí)現(xiàn)redisson分布式鎖,具有很好的參考價(jià)值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

自定義注解實(shí)現(xiàn)redisson分布式鎖

自定義注解

package com.example.demo.annotation;
import java.lang.annotation.*;
/**
 * desc: 自定義 redisson 分布式鎖注解
 *
 * @author: 邢陽(yáng)
 * @mail: xydeveloper@126.com
 * @create 2021-05-28 16:50
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Lock {
    /**
     * 鎖的key spel 表達(dá)式
     *
     * @return
     */
    String key();
    /**
     * 持鎖時(shí)間
     *
     * @return
     */
    long keepMills() default 20;
    /**
     * 沒有獲取到鎖時(shí),等待時(shí)間
     *
     * @return
     */
    long maxSleepMills() default 30;
}

aop解析注解

package com.example.demo.utils;
import com.example.demo.annotation.Lock;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
 * desc: 解析 自定義 redisson 分布式鎖注解
 *
 * @author: 邢陽(yáng)
 * @mail: xydeveloper@126.com
 * @create 2021-05-28 16:50
 */
@Aspect
@Component
public class LockAspect {
    @Autowired
    private RedissonClient redissonClient;
    /**
     * 用于SpEL表達(dá)式解析.
     */
    private final SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
    /**
     * 用于獲取方法參數(shù)定義名字.
     */
    private final DefaultParameterNameDiscoverer defaultParameterNameDiscoverer = new DefaultParameterNameDiscoverer();
    @Around("@annotation(com.example.demo.annotation.Lock)")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object object = null;
        RLock lock = null;
        try {
            // 獲取注解實(shí)體信息
            Lock lockEntity = (((MethodSignature) proceedingJoinPoint.getSignature()).getMethod())
                    .getAnnotation(Lock.class);
            // 根據(jù)名字獲取鎖實(shí)例
            lock = redissonClient.getLock(getKeyBySpeL(lockEntity.key(), proceedingJoinPoint));
            if (Objects.nonNull(lock)) {
                if (lock.tryLock(lockEntity.maxSleepMills(), lockEntity.keepMills(), TimeUnit.SECONDS)) {
                    object = proceedingJoinPoint.proceed();
                } else {
                    throw new RuntimeException();
                }
            }
        } finally {
            if (Objects.nonNull(lock) && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        return object;
    }
    /**
     * 獲取緩存的key
     * 
     * key 定義在注解上,支持SPEL表達(dá)式
     *
     * @return
     */
    public String getKeyBySpeL(String spel, ProceedingJoinPoint proceedingJoinPoint) {
        MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
        String[] paramNames = defaultParameterNameDiscoverer.getParameterNames(methodSignature.getMethod());
        EvaluationContext context = new StandardEvaluationContext();
        Object[] args = proceedingJoinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
            context.setVariable(paramNames[i], args[i]);
        }
        return String.valueOf(spelExpressionParser.parseExpression(spel).getValue(context));
    }
}

service中使用注解加鎖使用

/**
 * desc: 鎖
 *
 * @author: 邢陽(yáng)
 * @mail: xydeveloper@126.com
 * @create 2021-05-28 17:58
 */
@Service
public class LockService {
  	@Lock(key = "#user.id", keepMills = 10, maxSleepMills = 15)
    public String lock(User user) {
        System.out.println("持鎖");
        return "";
    }
}

redisson分布式鎖應(yīng)用

分布式架構(gòu)一定會(huì)用到分布式鎖。目前公司使用的基于redis的redisson分布式鎖。

應(yīng)用場(chǎng)景

1.訂單修改操作,首先要獲取該訂單的分布式鎖,能取到才能去操作。lockey可以是訂單的主鍵id。

2.庫(kù)存操作,也要按照客戶+倉(cāng)庫(kù)+sku維護(hù)鎖定該庫(kù)存,進(jìn)行操作。

代碼:

Redisson管理類

public class RedissonManager {
? ? private static RedissonClient redisson;
? ? static {
? ? ? ? Config config = new Config();
? ? ? ? config.useSentinelServers()
? ? ? ? ? ? ? ? .addSentinelAddress("redis://127.0.0.1:26379","redis://127.0.0.1:7301", "redis://127.0.0.1:7302")
? ? ? ? ? ? ? ? .setMasterName("mymaster")
? ? ? ? ? ? ? ? .setReadMode(ReadMode.SLAVE)
? ? ? ? ? ? ? ? .setTimeout(10000).setDatabase(0).setPassword("123***");
? ? ? ? redisson = Redisson.create(config);
? ? }
?
? ? /**
? ? ?* 獲取Redisson的實(shí)例對(duì)象
? ? ?* @return
? ? ?*/
? ? public static RedissonClient getRedisson(){ return redisson;}
}

分布式鎖

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import java.util.concurrent.TimeUnit;
public class DistributedLock {
? ? private static RedissonClient redissonClient = RedissonManager.getRedisson();
? ? public static boolean tryLock(String lockKey, TimeUnit unit, int waitTime, int leaseTime) {
? ? ? ? RLock lock = redissonClient.getLock(lockKey);
? ? ? ? try {
? ? ? ? ? ? return lock.tryLock(waitTime, leaseTime, unit);
? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? return false;
? ? ? ? }
? ? }
? ? public static void unlock(String lockKey) {
? ? ? ? RLock lock = redissonClient.getLock(lockKey);
? ? ? ? lock.unlock();
? ? }
}

測(cè)試類

public class RedissonTest {
? ? public static void main(String[] args) throws Exception{
? ? ? ? Thread.sleep(2000L);
? ? ? ? for (int i = 0; i < 3; i++) {
? ? ? ? ? ? new Thread(() -> {
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? //tryLock,第三個(gè)參數(shù)是等待時(shí)間,5秒內(nèi)獲取不到鎖,則直接返回。 第四個(gè)參數(shù) 30是30秒后強(qiáng)制釋放
? ? ? ? ? ? ? ? ? ? boolean hasLock = DistributedLock.tryLock("lockKey", TimeUnit.SECONDS,5,30);
? ? ? ? ? ? ? ? ? ? //獲得分布式鎖
? ? ? ? ? ? ? ? ? ? if(hasLock){
? ? ? ? ? ? ? ? ? ? ? ? System.out.println("idea1: " + Thread.currentThread().getName() + "獲得了鎖");
? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? /**
? ? ? ? ? ? ? ? ? ? ? ? ?* 由于在DistributedLock.tryLock設(shè)置的等待時(shí)間是5s,
? ? ? ? ? ? ? ? ? ? ? ? ?* 所以這里如果休眠的小于5秒,這第二個(gè)線程能獲取到鎖,
? ? ? ? ? ? ? ? ? ? ? ? ?* ?如果設(shè)置的大于5秒,則剩下的線程都不能獲取鎖。可以分別試試2s,和8s的情況
? ? ? ? ? ? ? ? ? ? ? ? ?*/
? ? ? ? ? ? ? ? ? ? ? ? Thread.sleep(10000L);
? ? ? ? ? ? ? ? ? ? ? ? DistributedLock.unlock("lockKey");
? ? ? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? System.out.println("idea1: " + Thread.currentThread().getName() + "無(wú)法獲取鎖");
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? }?
? ? ? ? ? ? }) .start();
? ? ? ? }
? ? }
}

我們?cè)俅蜷_一個(gè)idea,可以把代碼復(fù)制一份。同事啟動(dòng)兩個(gè)RedissonTest ,模擬了并發(fā)操作。

測(cè)試結(jié)果:

idea2: Thread-1獲得了鎖
idea2: Thread-0無(wú)法獲取鎖
idea2: Thread-2無(wú)法獲取鎖
 
 
idea1: Thread-2無(wú)法獲取鎖
idea1: Thread-0無(wú)法獲取鎖
idea1: Thread-1無(wú)法獲取鎖

從測(cè)試結(jié)果發(fā)現(xiàn),最后是只能有一個(gè)idea的一個(gè)線程能獲取到鎖。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java兩個(gè)integer數(shù)據(jù)判斷相等用==還是equals

    java兩個(gè)integer數(shù)據(jù)判斷相等用==還是equals

    本文主要介紹了java兩個(gè)integer數(shù)據(jù)判斷相等用==還是equals,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • SpringBoot使用自動(dòng)配置xxxAutoConfiguration

    SpringBoot使用自動(dòng)配置xxxAutoConfiguration

    這篇文章介紹了SpringBoot自動(dòng)配置xxxAutoConfiguration的使用方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12
  • Window中安裝構(gòu)建神器Jenkins詳解

    Window中安裝構(gòu)建神器Jenkins詳解

    Jenkins是一款開源 CI&CD 軟件,用于自動(dòng)化各種任務(wù),包括構(gòu)建、測(cè)試和部署軟件。支持各種運(yùn)行方式,可通過系統(tǒng)包、Docker 或者通過一個(gè)獨(dú)立的 Java 程序。是解放人工集成部署的自動(dòng)化構(gòu)建神器
    2021-07-07
  • java將文件轉(zhuǎn)成流文件返回給前端詳細(xì)代碼實(shí)例

    java將文件轉(zhuǎn)成流文件返回給前端詳細(xì)代碼實(shí)例

    Java編程語(yǔ)言提供了強(qiáng)大的文件處理和壓縮能力,下面這篇文章主要給大家介紹了關(guān)于java將文件轉(zhuǎn)成流文件返回給前端的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-07-07
  • java編程常用技術(shù)(推薦)

    java編程常用技術(shù)(推薦)

    下面小編就為大家?guī)?lái)一篇java編程常用技術(shù)(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧
    2016-06-06
  • 詳解JAVA后端實(shí)現(xiàn)統(tǒng)一掃碼支付:微信篇

    詳解JAVA后端實(shí)現(xiàn)統(tǒng)一掃碼支付:微信篇

    本篇文章主要介紹了詳解JAVA后端實(shí)現(xiàn)統(tǒng)一掃碼支付:微信篇,這里整理了詳細(xì)的代碼,有需要的小伙伴可以參考下。
    2017-01-01
  • 一文搞懂Spring AOP的五大通知類型

    一文搞懂Spring AOP的五大通知類型

    本文將詳細(xì)為大家介紹Spring AOP的五種通知類型(前置通知、后置通知、返回通知、異常通知、環(huán)繞通知),感興趣的朋友可以了解一下
    2022-06-06
  • Java字符串拼接的優(yōu)雅方式實(shí)例詳解

    Java字符串拼接的優(yōu)雅方式實(shí)例詳解

    字符串拼接一般使用“+”,但是“+”不能滿足大批量數(shù)據(jù)的處理,下面這篇文章主要給大家介紹了關(guān)于Java字符串拼接的幾種優(yōu)雅方式,需要的朋友可以參考下
    2021-07-07
  • Java多線程與優(yōu)先級(jí)詳細(xì)解讀

    Java多線程與優(yōu)先級(jí)詳細(xì)解讀

    這篇文章主要給大家介紹了關(guān)于Java中方法使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-08-08
  • java編程實(shí)現(xiàn)兩個(gè)大數(shù)相加代碼示例

    java編程實(shí)現(xiàn)兩個(gè)大數(shù)相加代碼示例

    這篇文章主要介紹了java編程實(shí)現(xiàn)兩個(gè)大數(shù)相加代碼示例,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-12-12

最新評(píng)論

青阳县| 金乡县| 泰和县| 眉山市| 新闻| 安溪县| 富宁县| 吉林市| 南郑县| 田东县| 房山区| 满城县| 静安区| 民县| 巴彦淖尔市| 错那县| 喀什市| 永川市| 左权县| 三明市| 义马市| 枣阳市| 易门县| 盐池县| 沛县| 习水县| 曲周县| 北海市| 成都市| 闸北区| 陇南市| 连山| 长兴县| 仁寿县| 永德县| 通海县| 望城县| 长沙市| 依安县| 洱源县| 汕头市|