亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解Redisson分布式限流的使用及原理

 更新時(shí)間:2025年02月21日 10:37:26   作者:重生之Java再愛我一次  
本文介紹了Redisson分布式限流的使用方法和原理,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1. 常見的分布式限流算法

1.1 固定窗口算法

原理:固定窗口算法是一種簡(jiǎn)單的限流算法。在固定時(shí)間窗口內(nèi),記錄請(qǐng)求的數(shù)量。例如,設(shè)定每10秒鐘最多允許5次請(qǐng)求,如果在當(dāng)前窗口內(nèi)的請(qǐng)求數(shù)超過限制,則拒絕請(qǐng)求。

優(yōu)點(diǎn):簡(jiǎn)單易實(shí)現(xiàn)。

缺點(diǎn):存在“流量突刺”的問題,也就是在窗口切換時(shí)可能會(huì)產(chǎn)生兩倍于閾值流量的請(qǐng)求

適用場(chǎng)景: 適合于對(duì)于突發(fā)流量容忍度高的場(chǎng)景。

1.2 滑動(dòng)窗口算法

原理: 滑動(dòng)窗口算法在固定窗口的基礎(chǔ)上,將一個(gè)計(jì)時(shí)窗口分成了若干個(gè)小窗口,然后每個(gè)小窗口維護(hù)一個(gè)獨(dú)立的計(jì)數(shù)器。當(dāng)請(qǐng)求的時(shí)間大于當(dāng)前窗口的最大時(shí)間時(shí),則將計(jì)時(shí)窗口向前平移一個(gè)小窗口。平移時(shí),將第一個(gè)小窗口的數(shù)據(jù)丟棄,然后將第二個(gè)小窗口設(shè)置為第一個(gè)小窗口,同時(shí)在最后面新增一個(gè)小窗口,將新的請(qǐng)求放在新增的小窗口中。同時(shí)要保證整個(gè)窗口中所有小窗口的請(qǐng)求數(shù)目之后不能超過設(shè)定的閾值。

優(yōu)點(diǎn): 相比滑動(dòng)窗口,它能夠更精確地控制請(qǐng)求頻率,避免了“流量突刺”問題。

缺點(diǎn): 滑動(dòng)窗口算法是固定窗口的一種改進(jìn),但從根本上并沒有真正解決固定窗口算法的臨界突發(fā)流量問題。實(shí)現(xiàn)相對(duì)復(fù)雜,要求記錄每個(gè)時(shí)間窗口的請(qǐng)求數(shù),需要更多的存儲(chǔ)和計(jì)算資源。

適用場(chǎng)景: 比較適合對(duì)于不能容忍臨界突發(fā)流量的場(chǎng)景。

1.3 漏桶算法

原理: 漏桶算法將請(qǐng)求放入一個(gè)桶中,桶以固定速率漏出請(qǐng)求。如果桶滿了,新的請(qǐng)求將被丟棄。請(qǐng)求的流入速率可以不均勻,但漏出的速率是固定的,確保請(qǐng)求按照固定速率被處理。

優(yōu)點(diǎn): 適用于需要平滑處理突發(fā)流量的場(chǎng)景,能夠把瞬時(shí)流量平滑到平穩(wěn)流量。

缺點(diǎn): 請(qǐng)求的流入速率過快會(huì)導(dǎo)致請(qǐng)求丟失,需要合理設(shè)置桶的容量和漏水速率。不支持突發(fā)流量。

適用場(chǎng)景: 例如保護(hù)數(shù)據(jù)庫的限流,先把對(duì)數(shù)據(jù)庫的訪問加入到桶中,工作線程再以數(shù)據(jù)庫能夠承受的請(qǐng)求壓力從桶中取出請(qǐng)求,去訪問數(shù)據(jù)庫。

1.4 令牌桶算法

原理:令牌桶算法是對(duì)漏斗算法的一種改進(jìn),除了能夠起到限流的作用外,還允許一定程度的流量突發(fā)。在令牌桶算法中,存在一個(gè)令牌桶,算法中存在一種機(jī)制以恒定的速率向令牌桶中放入令牌。令牌桶也有一定的容量,如果滿了令牌就無法放進(jìn)去了。當(dāng)請(qǐng)求來時(shí),會(huì)首先到令牌桶中去拿令牌,如果拿到了令牌,則該請(qǐng)求會(huì)被處理,并消耗掉拿到的令牌;如果令牌桶為空,則該請(qǐng)求會(huì)被丟棄。

優(yōu)點(diǎn): 允許突發(fā)流量,且能平滑處理請(qǐng)求流量。

缺點(diǎn):對(duì)桶的大小和令牌生成速率要求較高,對(duì)存儲(chǔ)資源的需求較大,因?yàn)樾枰S護(hù)令牌桶。

適用場(chǎng)景: 適合電商搶購或者微博出現(xiàn)熱點(diǎn)事件這種場(chǎng)景,因?yàn)樵谙蘖鞯耐瑫r(shí)可以應(yīng)對(duì)一定的突發(fā)流量。如果采用漏桶那樣的均勻速度處理請(qǐng)求的算法,在發(fā)生熱點(diǎn)時(shí)間的時(shí)候,會(huì)造成大量的用戶無法訪問,對(duì)用戶體驗(yàn)的損害比較大。

2. Redisson分布式限流的使用

Redisson 是一款基于 Redis 的 Java 分布式工具庫。它封裝了 Redis 的底層操作,提供了分布式鎖、分布式集合、分布式隊(duì)列、分布式執(zhí)行器等功能,幫助開發(fā)者更高效地實(shí)現(xiàn)分布式系統(tǒng)。Redisson 提供了一系列高級(jí)的數(shù)據(jù)結(jié)構(gòu)接口(如 RMapRSetRLock 等),并支持多種部署模式(單節(jié)點(diǎn)、主從、哨兵、集群等)。

在生產(chǎn)環(huán)境下,我們使用的更多的是其分布式鎖功能,但是Redisson還提供了分布式限流的功能,相比于 Guava 提供的單機(jī)限流、Sentinel提供的接口限流,Redisson的分布式限流更便于用戶去自定義符合自身業(yè)務(wù)的限流規(guī)則。

2.1 引入Maven依賴

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.43.0</version>
</dependency>

2.2 封裝Redisson限流工具類

我這里針對(duì)Redisson做了二次封裝,配合配置文件實(shí)現(xiàn)更靈活的限流策略

限流配置類RateLimitProperties

import lombok.Data;
import org.redisson.api.RateIntervalUnit;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
@ConfigurationProperties("rate-limit")
@Data
public class RateLimitProperties {
    private Config defaultConfig;
    private List<Config> configs;

    @Data
    public static class Config {
        private String keyPrefix;
        private long timeOut;
        private RateIntervalUnit rateIntervalUnit;
        private long count;
    }

    /**
     * 根據(jù)key獲取對(duì)應(yīng)匹配的前綴的限流配置
     * @param key key
     * @return 限流配置
     */
    public Config getRateLimitConfig(String key) {
        return configs.stream()
                .filter(e -> key.startsWith(e.getKeyPrefix()))
                .findFirst()
                .orElse(defaultConfig);
    }

}

限流配置文件application.yaml

# 限流配置
rate-limit:
  # 默認(rèn)限流配置,如果前綴沒有匹配上,則使用默認(rèn)配置
  default-config:
    model-name-prefix: default
    time-out: 30
    rate-interval-unit: seconds
    count: 1
  configs:
    - key-prefix: test
      time-out: 1
      rate-interval-unit: seconds
      count: 2

限流工具類RateLimitUtil

import com.gzb.app.config.RateLimitProperties;
import com.gzb.app.constant.RedisConstant;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * 限流工具類
 */
@Component
public class RateLimitUtil {
    @Autowired
    private RateLimitProperties rateLimitProperties;
    @Autowired
    private RedissonClient redissonClient;
    
    /**
     * 嘗試獲取一個(gè)限流器許可,如果當(dāng)前沒有足夠的令牌,調(diào)用線程將被阻塞,直到有足夠的令牌
     * @param key 限流器的唯一標(biāo)識(shí)
     */
    public void acquire(String key) {
        getRedissonRateLimiter(key).acquire();
    }

    /**
     * 嘗試立即獲取一個(gè)限流器許可,如果當(dāng)前沒有足夠的令牌,立即返回 false
     * @param key 限流器的唯一標(biāo)識(shí)
     * @return 成功:true 失敗:false
     */
    public boolean tryAcquire(String key) {
        return getRedissonRateLimiter(key).tryAcquire();
    }

    /**
     * 嘗試在指定時(shí)間內(nèi)獲取一個(gè)限流器許可,如果在指定時(shí)間內(nèi)沒有足夠的令牌,立即返回 false
     * @param key 限流器的唯一標(biāo)識(shí)
     * @param time 等待的時(shí)間長(zhǎng)度
     * @param timeUnit 時(shí)間單位
     * @return 成功:true 失?。篺alse
     */
    public boolean tryAcquire(String key, long time, TimeUnit timeUnit) {
        return getRedissonRateLimiter(key).tryAcquire(time, timeUnit);
    }

    /**
     * 獲取限流器,如果限流器不存在,則根據(jù)配置創(chuàng)建一個(gè)新的限流器
     * @param key 限流器的唯一標(biāo)識(shí)
     * @return RedissonRateLimiter 限流器實(shí)例
     */
    public RRateLimiter getRedissonRateLimiter(String key) {
        RateLimitProperties.Config config = rateLimitProperties.getRateLimitConfig(key);
        long count = config.getCount();
        long timeOut = config.getTimeOut();
        RateIntervalUnit rateIntervalUnit = config.getRateIntervalUnit();
        RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);
        // 如果限流器不存在,就創(chuàng)建一個(gè)限流器
        if (!rateLimiter.isExists()) {
            rateLimiter.trySetRate(RateType.OVERALL, count, timeOut, rateIntervalUnit);
            return rateLimiter;
        }
        checkIfConfigNeedUpdate(rateLimiter, config);
        return rateLimiter;
    }

    /**
     * 檢查限流器配置是否發(fā)生修改,如果配置發(fā)生變化,則刪除舊的限流器并重新創(chuàng)建
     *
     * @param rateLimiter 限流器
     * @param rateLimitConfig 限流配置
     */
    private void checkIfConfigNeedUpdate(RRateLimiter rateLimiter, RateLimitProperties.Config rateLimitConfig) {
        long count = rateLimitConfig.getCount();
        long timeOut = rateLimitConfig.getTimeOut();
        RateIntervalUnit rateIntervalUnit = rateLimitConfig.getRateIntervalUnit();
        // 獲取之前限流器的配置信息
        RateLimiterConfig config = rateLimiter.getConfig();
        if (rateIntervalUnit.toMillis(timeOut) != config.getRateInterval() || count != config.getRate()) {
            // 如果當(dāng)前限流器的配置與配置文件不一致,說明服務(wù)器重啟過
            rateLimiter.delete();
            // 配置文件為準(zhǔn),重新設(shè)置
            rateLimiter.trySetRate(RateType.OVERALL, count, timeOut, rateIntervalUnit);
        }
    }
}

2.3 測(cè)試代碼

@RestController
@Slf4j
public class RedissonController {
    @Autowired
    private RateLimitUtil rateLimitUtil;

    @GetMapping("/rateLimit/{key}")
    public void rateLimit(@PathVariable String key) {
        log.info("{} start get access token, current time = {}", Thread.currentThread().getName(), System.currentTimeMillis());
        rateLimitUtil.acquire(key);
        log.info("{} successfully start get access token, current time = {}", Thread.currentThread().getName(), System.currentTimeMillis());
    }
}

3. Redisson分布式限流原理

3.1 設(shè)置限流配置方法trySetRate

在使用限流器之前,都需要提前設(shè)置限流配置,否則限流代碼會(huì)報(bào)錯(cuò)(后面會(huì)提到具體哪一行代碼)

跟進(jìn)RedissonRateLimitertrySetRate方法,可以找到下圖中的方法,可見設(shè)置限流配置很簡(jiǎn)單,只是一段很簡(jiǎn)單的Lua腳本,在腳本中往Hash數(shù)據(jù)結(jié)構(gòu)中寫入了我們之前配置的限流參數(shù)。

在這里插入圖片描述

3.2 acquire限流方法原理

跟進(jìn)RedissonRateLimiteracquire方法,可以找到一段Lua腳本代碼,在展開講解Lua腳本之前,需要先了解一下限流需要用到哪些Redis鍵值

在這里插入圖片描述

圖片中我使用的key是test:

首先是{key},對(duì)應(yīng)著圖片中的test,是哈希數(shù)據(jù)類型,里面存儲(chǔ)著限流配置,比如:rate、interval等信息,這里的keepAliveTime先不做考慮,與本次要講解的核心限流邏輯無太大關(guān)系。

在這里插入圖片描述

接著是{key}:value,對(duì)應(yīng)著圖片中的{test}:value,是字符串?dāng)?shù)據(jù)類型,value是一個(gè)數(shù)字,表示可用的令牌桶數(shù)量。

在這里插入圖片描述

再接著是{key}:permits,對(duì)應(yīng)著圖片中的{test}:permits,是一個(gè)有序集合,保存著限流過程中的訪問信息。有序集合中的value使用隨機(jī)數(shù)和你要獲取的token數(shù)量拼接作為value,防止value的重復(fù),score存儲(chǔ)著訪問時(shí)候的時(shí)間戳。

在這里插入圖片描述

-- 獲取限流器的配置值:rate、interval 和 type
local rate = redis.call('hget', KEYS[1], 'rate');          -- 獲取限制速率(每秒允許的請(qǐng)求次數(shù))
local interval = redis.call('hget', KEYS[1], 'interval');  -- 獲取限流的時(shí)間間隔(單位通常為秒)
local type = redis.call('hget', KEYS[1], 'type');          -- 獲取限流類型(如 OVERALL 或 PRE_WARMING)

-- 如果配置沒有初始化(即獲取的值為空),拋出錯(cuò)誤
-- 這里對(duì)應(yīng)著一開始要設(shè)置好限流配置參數(shù),否則Lua腳本執(zhí)行過程會(huì)拋出異常
assert(rate ~= false and interval ~= false and type ~= false, 'RateLimiter is not initialized')

-- 當(dāng)前請(qǐng)求令牌數(shù)的鍵
local valueName = KEYS[2];   
-- 請(qǐng)求令牌記錄的鍵
local permitsName = KEYS[4]; 

-- 如果限流類型是 PRE_WARMING,調(diào)整鍵值名
if type == '1' then
    valueName = KEYS[3];   -- 如果是 PRE_WARMING,則使用不同的令牌數(shù)鍵
    permitsName = KEYS[5];  -- 如果是 PRE_WARMING,則使用不同的令牌記錄鍵
end;

-- 檢查請(qǐng)求的令牌數(shù)是否超過了令牌桶的大小
-- 例如:rate設(shè)置為10,在acqure的時(shí)候大于10,Lua腳本就會(huì)報(bào)錯(cuò)
assert(tonumber(rate) >= tonumber(ARGV[1]), 'Requested permits amount cannot exceed defined rate');

-- 獲取當(dāng)前剩余可用的令牌數(shù)
local currentValue = redis.call('get', valueName);

-- 變量 res 用于存儲(chǔ)返回值,指示是否可以獲取令牌
-- 如果是nil表示令牌充足,獲取令牌成功
-- 如果是一個(gè)數(shù)字,則表示令牌不足,需要要等待的時(shí)間
local res;

-- 表明不是第一次獲取令牌
if currentValue ~= false then
    -- 獲取在過去一段時(shí)間內(nèi)過期的請(qǐng)求記錄
    local expiredValues = redis.call('zrangebyscore', permitsName, 0, tonumber(ARGV[2]) - interval);
    local released = 0;  -- 已釋放的令牌數(shù)

    -- 統(tǒng)計(jì)過期的請(qǐng)求記錄中的令牌數(shù)
    for i, v in ipairs(expiredValues) do
        local random, permits = struct.unpack('Bc0I', v);
        released = released + permits;
    end;

    -- 如果有過期的令牌,進(jìn)行釋放處理
    if released > 0 then
        -- 從令牌記錄中移除過期的項(xiàng)
        redis.call('zremrangebyscore', permitsName, 0, tonumber(ARGV[2]) - interval);
        
        -- 以下if-else代碼用于保證可用的令牌個(gè)數(shù)和令牌訪問記錄中使用的令牌個(gè)數(shù)之和小于桶的容量rate
        if tonumber(currentValue) + released > tonumber(rate) then
            local values = redis.call('zrange', permitsName, 0, -1);  -- 獲取所有令牌記錄
            local used = 0;  -- 已使用的令牌數(shù)
            -- 統(tǒng)計(jì)所有已使用的令牌數(shù)
            for i, v in ipairs(values) do
                local random, permits = struct.unpack('Bc0I', v);
                used = used + permits;
            end;
            -- 調(diào)整當(dāng)前令牌數(shù),確保不會(huì)超過桶的大小
            currentValue = tonumber(rate) - used;
        else
            -- 否則,直接增加釋放的令牌數(shù)
            currentValue = tonumber(currentValue) + released;
        end;
        -- 更新令牌數(shù)
        redis.call('set', valueName, currentValue);
    end;

    -- 如果當(dāng)前令牌數(shù)小于請(qǐng)求的令牌數(shù),計(jì)算下一次可以獲取令牌的時(shí)間
    if tonumber(currentValue) < tonumber(ARGV[1]) then
        local firstValue = redis.call('zrange', permitsName, 0, 0, 'withscores');  -- 獲取最早的請(qǐng)求記錄
        res = 3 + interval - (tonumber(ARGV[2]) - tonumber(firstValue[2]));  -- 計(jì)算等待時(shí)間
    else
        -- 如果當(dāng)前令牌數(shù)足夠,記錄請(qǐng)求并減少令牌數(shù)
        redis.call('zadd', permitsName, ARGV[2], struct.pack('Bc0I', string.len(ARGV[3]), ARGV[3], ARGV[1]));
        redis.call('decrby', valueName, ARGV[1]);
        res = nil;  -- 沒有錯(cuò)誤,返回值為空
    end;
-- 如果是第一次獲取令牌,則設(shè)置當(dāng)前可用的令牌數(shù),添加訪問記錄,扣減可用令牌數(shù)量
else
    -- 設(shè)置當(dāng)前可用的令牌數(shù)
    redis.call('set', valueName, rate);
    -- 新增領(lǐng)票訪問記錄
    redis.call('zadd', permitsName, ARGV[2], struct.pack('Bc0I', string.len(ARGV[3]), ARGV[3], ARGV[1]));
    -- 扣減可用令牌數(shù)量
    redis.call('decrby', valueName, ARGV[1]);
    -- 沒有錯(cuò)誤,返回值為空,表示獲取令牌成功
    res = nil;  
end;

-- 返回結(jié)果,可能是等待時(shí)間或空值
-- 如果是nil表示令牌充足,獲取令牌成功
-- 如果是一個(gè)數(shù)字,則表示令牌不足,需要要等待的時(shí)間
return res;

這里有一張流程圖可以很好的演示Lua腳本的限流邏輯:

在這里插入圖片描述

3.3 使用Redisson分布式限流的注意事項(xiàng)

  • 限流配置Rate不要設(shè)置過大

    從Lua腳本中我們可以看到,Rate的值限制著有序集合中的限流訪問記錄,如果Rate值過大可能會(huì)導(dǎo)致有序集合中存儲(chǔ)的數(shù)據(jù)激增,從而Redis的內(nèi)存增加,并且使得Lua腳本的執(zhí)行效率下降,緊跟著就是限流功能的效率下降,傾向于小Rate+小時(shí)間窗口的方式,這種設(shè)置方式請(qǐng)求也會(huì)更均勻一些。

  • 限流的上限取決于Redis的性能

    RRateLimiter的限流能力受制于Redis實(shí)例的性能上限。例如,如果Redis實(shí)例的QPS上限是1w,那么通過RRateLimiter實(shí)現(xiàn)2w QPS限流是不可能的。要突破單個(gè)Redis實(shí)例性能的限制,可以通過拆分多個(gè)限流器來實(shí)現(xiàn)。具體做法是創(chuàng)建多個(gè)限流器,使用不同的名稱,并在各臺(tái)機(jī)器上隨機(jī)選擇一個(gè)限流器進(jìn)行限流,這樣總流量就可以被分散到多個(gè)限流器上,從而提升整體限流上限。

到此這篇關(guān)于詳解Redisson分布式限流的使用及原理的文章就介紹到這了,更多相關(guān)Redisson分布式限流內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • JAVA并發(fā)圖解

    JAVA并發(fā)圖解

    這篇文章主要介紹了JAVA的并發(fā),文中圖解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2021-09-09
  • SpringMVC post請(qǐng)求中文亂碼問題解決

    SpringMVC post請(qǐng)求中文亂碼問題解決

    這篇文章主要介紹了SpringMVC post請(qǐng)求中文亂碼問題解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • SpringBoot整合MongoDB全過程

    SpringBoot整合MongoDB全過程

    這篇文章主要介紹了SpringBoot整合MongoDB全過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • 淺析SpringBoot中使用thymeleaf找不到.HTML文件的原因

    淺析SpringBoot中使用thymeleaf找不到.HTML文件的原因

    這篇文章主要介紹了SpringBoot中使用thymeleaf找不到.HTML文件的原因分析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • 換了最新的idea如何將原來舊版本的idea設(shè)置導(dǎo)進(jìn)新的idea中

    換了最新的idea如何將原來舊版本的idea設(shè)置導(dǎo)進(jìn)新的idea中

    這篇文章主要介紹了換了最新的idea如何將原來舊版本的idea設(shè)置導(dǎo)進(jìn)新的idea中,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • 你知道怎么用Spring的三級(jí)緩存解決循環(huán)依賴嗎

    你知道怎么用Spring的三級(jí)緩存解決循環(huán)依賴嗎

    這篇文章主要為大家詳細(xì)介紹了Spring的三級(jí)緩存解決循環(huán)依賴,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • 利用HttpUrlConnection 上傳 接收文件的實(shí)現(xiàn)方法

    利用HttpUrlConnection 上傳 接收文件的實(shí)現(xiàn)方法

    下面小編就為大家?guī)硪黄肏ttpUrlConnection 上傳 接收文件的實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-11-11
  • Java 對(duì)稱加密幾種算法分別實(shí)現(xiàn)

    Java 對(duì)稱加密幾種算法分別實(shí)現(xiàn)

    這篇文章主要介紹了Java 對(duì)稱加密使用DES / 3DES / AES 這三種算法分別實(shí)現(xiàn)的相關(guān)資料,這里提供了實(shí)例代碼,需要的朋友可以參考下
    2017-01-01
  • java線程并發(fā)控制同步工具CountDownLatch

    java線程并發(fā)控制同步工具CountDownLatch

    這篇文章主要為大家介紹了java線程并發(fā)控制同步工具CountDownLatch使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • SpringBoot結(jié)合ProGuard實(shí)現(xiàn)代碼混淆(最新版)

    SpringBoot結(jié)合ProGuard實(shí)現(xiàn)代碼混淆(最新版)

    這篇文章主要介紹了SpringBoot結(jié)合ProGuard實(shí)現(xiàn)代碼混淆(最新版),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10

最新評(píng)論