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

詳解Java中CountDownLatch異步轉(zhuǎn)同步工具類

 更新時間:2021年06月30日 10:38:27   作者:lingzhi_ying  
今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著CountDownLatch異步轉(zhuǎn)同步工具類展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下

使用場景

由于公司業(yè)務(wù)需求,需要對接socket、MQTT等消息隊(duì)列。
眾所周知 socket 是雙向通信,socket的回復(fù)是人為定義的,客戶端推送消息給服務(wù)端,服務(wù)端的回復(fù)是兩條線。無法像http請求有回復(fù)。
下發(fā)指令給硬件時,需要校驗(yàn)此次數(shù)據(jù)下發(fā)是否成功。
用戶體驗(yàn)而言,點(diǎn)擊按鈕就要知道此次的下發(fā)成功或失敗。

在這里插入圖片描述

如上圖模型,

第一種方案使用Tread.sleep
優(yōu)點(diǎn):占用資源小,放棄當(dāng)前cpu資源
缺點(diǎn): 回復(fù)速度快,休眠時間過長,仍然需要等待休眠結(jié)束才能返回,響應(yīng)速度是固定的,無法及時響應(yīng)第二種方案使用CountDownLatch

package com.lzy.demo.delay;

import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class CountDownLatchPool {

    //countDonw池
    private final static Map<Integer, CountDownLatch> countDownLatchMap = new ConcurrentHashMap<>();
    //延遲隊(duì)列
    private final static DelayQueue<MessageDelayQueueUtil> delayQueue = new DelayQueue<>();

    private volatile static boolean flag =false;
    //單線程池
    private final static ExecutorService t = new ThreadPoolExecutor(1, 1,
        0L, TimeUnit.MILLISECONDS,
        new ArrayBlockingQueue<>(1));

    public static void addCountDownLatch(Integer messageId) {
        CountDownLatch countDownLatch = countDownLatchMap.putIfAbsent(messageId,new CountDownLatch(1) );
        if(countDownLatch == null){
            countDownLatch = countDownLatchMap.get(messageId);
        }
        try {
            addDelayQueue(messageId);
            countDownLatch.await(3L, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("阻塞等待結(jié)束~~~~~~");
    }

    public static void removeCountDownLatch(Integer messageId){
        CountDownLatch countDownLatch = countDownLatchMap.get(messageId);
        if(countDownLatch == null)
            return;
        countDownLatch.countDown();
        countDownLatchMap.remove(messageId);
        System.out.println("清除Map數(shù)據(jù)"+countDownLatchMap);
    }

    private static void addDelayQueue(Integer messageId){
        delayQueue.add(new MessageDelayQueueUtil(messageId));
        clearMessageId();
    }

    private static void clearMessageId(){
        synchronized (CountDownLatchPool.class){
            if(flag){
                return;
            }
            flag = true;
        }
        t.execute(()->{
            while (delayQueue.size() > 0){
                System.out.println("進(jìn)入線程并開始執(zhí)行");
                try {
                    MessageDelayQueueUtil take = delayQueue.take();
                    Integer messageId1 = take.getMessageId();
                    removeCountDownLatch(messageId1);
                    System.out.println("清除隊(duì)列數(shù)據(jù)"+messageId1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            flag = false;
            System.out.println("結(jié)束end----");
        });
    }

    public static void main(String[] args) throws InterruptedException {
        /*
        測試超時清空map
        new Thread(()->addCountDownLatch(1)).start();
        new Thread(()->addCountDownLatch(2)).start();
        new Thread(()->addCountDownLatch(3)).start();
        */
        //提前創(chuàng)建線程,清空countdown
        new Thread(()->{
            try {
                Thread.sleep(500L);
                removeCountDownLatch(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        //開始阻塞
        addCountDownLatch(1);
    	//通過調(diào)整上面的sleep我們發(fā)現(xiàn)阻塞市場取決于countDownLatch.countDown()執(zhí)行時間
    	System.out.println("阻塞結(jié)束----");
    }
}
class MessageDelayQueueUtil implements Delayed {

    private Integer messageId;
    private long avaibleTime;

    public Integer getMessageId() {
        return messageId;
    }

    public void setMessageId(Integer messageId) {
        this.messageId = messageId;
    }

    public long getAvaibleTime() {
        return avaibleTime;
    }

    public void setAvaibleTime(long avaibleTime) {
        this.avaibleTime = avaibleTime;
    }

    public MessageDelayQueueUtil(Integer messageId){
        this.messageId = messageId;
        //avaibleTime = 當(dāng)前時間+ delayTime
        //重試3次,每次3秒+1秒的延遲
        this.avaibleTime=3000*3+1000 + System.currentTimeMillis();
    }

    @Override
    public long getDelay(TimeUnit unit) {
        long diffTime= avaibleTime- System.currentTimeMillis();
        return unit.convert(diffTime,TimeUnit.MILLISECONDS);
    }

    @Override
    public int compareTo(Delayed o) {
        //compareTo用在DelayedUser的排序
        return (int)(this.avaibleTime - ((MessageDelayQueueUtil) o).getAvaibleTime());
    }
}

由于socket并不確定每次都會有數(shù)據(jù)返回,所以map的數(shù)據(jù)會越來越大,最終導(dǎo)致內(nèi)存溢出
需定時清除map內(nèi)的無效數(shù)據(jù)。
可以使用DelayedQuene延遲隊(duì)列來處理,相當(dāng)于給對象添加一個過期時間

使用方法 addCountDownLatch 等待消息,異步回調(diào)消息清空removeCountDownLatch

到此這篇關(guān)于詳解Java中CountDownLatch異步轉(zhuǎn)同步工具類的文章就介紹到這了,更多相關(guān)CountDownLatch異步轉(zhuǎn)同步工具類內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java請求調(diào)用參數(shù)格式為form-data類型的接口代碼示例

    Java請求調(diào)用參數(shù)格式為form-data類型的接口代碼示例

    這篇文章主要給大家介紹了關(guān)于Java請求調(diào)用參數(shù)格式為form-data類型的接口的相關(guān)資料,文中給出了詳細(xì)的代碼示例,對大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08
  • 親身體驗(yàn)Intellij?Idea從卡頓到順暢全過程

    親身體驗(yàn)Intellij?Idea從卡頓到順暢全過程

    這篇文章主要介紹了親身體驗(yàn)Intellij?Idea從卡頓到順暢全過程,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Spring Boot兩種全局配置和兩種注解的操作方法

    Spring Boot兩種全局配置和兩種注解的操作方法

    Spring Boot使用一個application.properties或者application.yaml的文件作為全局配置文件,本文重點(diǎn)給大家介紹Spring Boot兩種全局配置和兩種注解的配置方法,感興趣的朋友一起看看吧
    2021-06-06
  • Java優(yōu)秀測試框架TestNG詳解

    Java優(yōu)秀測試框架TestNG詳解

    這篇文章主要為大家詳細(xì)介紹了Java優(yōu)秀測試框架TestNG,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • 詳解APP微信支付(java后臺_統(tǒng)一下單和回調(diào))

    詳解APP微信支付(java后臺_統(tǒng)一下單和回調(diào))

    這篇文章主要介紹了APP微信支付(java后臺_統(tǒng)一下單和回調(diào)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • Java實(shí)現(xiàn)在線語音識別

    Java實(shí)現(xiàn)在線語音識別

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)在線語音識別功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • Java排序方法sort用法詳解

    Java排序方法sort用法詳解

    這篇文章主要為大家詳細(xì)介紹了Java排序方法sort用法,對數(shù)組、集合的排序方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Java必備知識之位運(yùn)算及常見進(jìn)制解讀

    Java必備知識之位運(yùn)算及常見進(jìn)制解讀

    從現(xiàn)代計(jì)算機(jī)中所有的數(shù)據(jù)二進(jìn)制的形式存儲在設(shè)備中。即 0、1 兩種狀態(tài),計(jì)算機(jī)對二進(jìn)制數(shù)據(jù)進(jìn)行的運(yùn)算(+、-、*、/)都是叫位運(yùn)算,即將符號位共同參與運(yùn)算的運(yùn)算
    2021-10-10
  • springboot CompletableFuture并行計(jì)算及使用方法

    springboot CompletableFuture并行計(jì)算及使用方法

    CompletableFuture基于 Future 和 CompletionStage 接口,利用線程池、回調(diào)函數(shù)、異常處理、組合操作等機(jī)制,提供了強(qiáng)大而靈活的異步編程功能,這篇文章主要介紹了springboot CompletableFuture并行計(jì)算及使用方法,需要的朋友可以參考下
    2024-05-05
  • SpringBoot + Spring Security 基本使用及個性化登錄配置詳解

    SpringBoot + Spring Security 基本使用及個性化登錄配置詳解

    這篇文章主要介紹了SpringBoot + Spring Security 基本使用及個性化登錄配置詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05

最新評論

眉山市| 阿勒泰市| 土默特右旗| 嘉荫县| 子洲县| 荥经县| 陈巴尔虎旗| 登封市| 揭西县| 府谷县| 南陵县| 拉萨市| 亚东县| 濮阳市| 东宁县| 太仆寺旗| 涟水县| 邳州市| 汶川县| 长顺县| 广平县| 延川县| 曲水县| 纳雍县| 苍溪县| 临沭县| 灵璧县| 遵化市| 明溪县| 婺源县| 屯留县| 亳州市| 大新县| 大港区| 孟津县| 新闻| 噶尔县| 安图县| 宜都市| 大冶市| 宜宾县|