java CountDownLatch用法簡介

CountDownLatch倒計數鎖存器

CountDownLatch:用于協同控制一個或多個線程等待在其他線程中執行的一組操作完成,然后再繼續執行

CountDownLatch用法

  1. 構造方法:CountDownLatch(int count),count指定等待的條件數(任務數、操作數),不可再更改
  2. 等待方法:await(),阻塞等待線程直到count減少為0,count為0時,不會阻塞,繼續執行
  3. boolean await(long timeout,TimeUnit
    unit):可以設置超時時間的await方法,返回true表示等待條件到達;false表示條件未來到達,但超時了
  4. long getCount():獲取當前計數值,常用于調試或者測試
    ps:CountDownLatch注意事項:只可使用一次,不能重復使用,計數變為0之后,就不可再用

CountDownLatch適用場景

  1. 等待多個條件完成,countDownLatch(N)這個多個條件可以是:等待N個線程、等待N個操作、等待某操作的N次執行
  2. 用于并發測試,等待多個線程一起出發

CountDownLatch例子

import java.util.Optional;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.stream.IntStream;public class JDKCountDown {private static final Random random = new Random(System.currentTimeMillis());public static void main(String[] args) throws InterruptedException {Optional.of("準備多線程處理任務。").ifPresent(System.out::println);final CountDownLatch countDownLatch = new CountDownLatch(5);IntStream.rangeClosed(1,5).forEach(i -> new Thread(()->{try {Optional.of("線程" + Thread.currentThread().getName() + " 開始執行任務。").ifPresent(System.out::println);Thread.sleep(random.nextInt(1000));Optional.of("線程" + Thread.currentThread().getName() + " 執行任務結束。").ifPresent(System.out::println);} catch (InterruptedException e) {e.printStackTrace();}countDownLatch.countDown();}, "Thread-"+i).start());countDownLatch.await();Optional.of("多線程處理任務結束。準備第二階段的工作").ifPresent(System.out::println);Optional.of("------------------------------------").ifPresent(System.out::println);Optional.of("FINISH").ifPresent(System.out::println);}
}

執行之后的結果

準備多線程處理任務。
線程Thread-3 開始執行任務。
線程Thread-4 開始執行任務。
線程Thread-5 開始執行任務。
線程Thread-2 開始執行任務。
線程Thread-1 開始執行任務。
線程Thread-2 執行任務結束。
線程Thread-1 執行任務結束。
線程Thread-3 執行任務結束。
線程Thread-5 執行任務結束。
線程Thread-4 執行任務結束。
多線程處理任務結束。準備第二階段的工作
------------------------------------
FINISH

我們手寫一個簡單SimpleCountDown

1.需要一個totalCount指定等待的條件數(任務數、操作數)
2.需要一個countDown計算有幾個線程 結束了

上代碼
/*** 簡單倒計時工具類,用于多線程間協調完成計數操作*/
public class SimpleCountDown {/** 總需要達到的倒計數次數(不可變) */private final int totalCount;/** 當前倒計數值 */private int countDown;/** 是否被取消(volatile保證可見性) */private volatile boolean canceled = false;/*** 構造方法* @param totalCount 需要完成的總倒計數次數*/public SimpleCountDown(int totalCount) {this.totalCount = totalCount;}/*** 執行一次倒計數操作(線程安全)* <p>增加當前計數值并通知所有等待線程</p>*/public void down(){synchronized (this){this.countDown++;this.notifyAll(); // 通知所有等待線程檢查條件}}/*** 等待直到完成所有倒計數操作* @throws InterruptedException 若當前線程被中斷則拋出異常*/public void await() throws InterruptedException {synchronized (this){while (countDown != totalCount){ // 使用while防止虛假喚醒this.wait();}}}
}
測試類
import java.util.Optional;
import java.util.Random;
import java.util.stream.IntStream;/*** 演示SimpleCountDown倒計時門閂的使用示例類*/
public class SimpleCountDownClient {// 隨機數生成器,用于模擬線程任務的隨機執行時間private static final Random random = new Random(System.currentTimeMillis());public static void main(String[] args) throws InterruptedException {// 輸出任務開始提示Optional.of("準備多線程處理任務。").ifPresent(System.out::println);// 初始化計數器為5,表示需要等待5個線程完成final SimpleCountDown countDownLatch = new SimpleCountDown(5);// 啟動5個線程執行任務IntStream.rangeClosed(1, 5).forEach(i -> {new Thread(() -> {try {// 線程任務開始通知Optional.of("線程" + Thread.currentThread().getName() + " 開始執行任務。").ifPresent(System.out::println);// 模擬隨機執行時間(0-1000毫秒)Thread.sleep(random.nextInt(1000));// 任務完成通知Optional.of("線程" + Thread.currentThread().getName() + " 執行任務結束。").ifPresent(System.out::println);} catch (InterruptedException e) {e.printStackTrace();} finally {// 通知計數器完成一個任務countDownLatch.down();}}, "Thread-" + i).start();});// 阻塞等待所有線程完成countDownLatch.await();// 所有線程完成后輸出后續階段提示Optional.of("多線程處理任務結束。準備第二階段的工作").ifPresent(System.out::println);Optional.of("------------------------------------").ifPresent(System.out::println);Optional.of("FINISH").ifPresent(System.out::println);}
}

執行的結果

準備多線程處理任務。
線程Thread-1 開始執行任務。
線程Thread-5 開始執行任務。
線程Thread-3 開始執行任務。
線程Thread-4 開始執行任務。
線程Thread-2 開始執行任務。
線程Thread-5 執行任務結束。
線程Thread-1 執行任務結束。
線程Thread-2 執行任務結束。
線程Thread-3 執行任務結束。
線程Thread-4 執行任務結束。
多線程處理任務結束。準備第二階段的工作
------------------------------------
FINISH

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/79275.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/79275.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/79275.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Leetcode - 雙周賽135

目錄 一、3512. 使數組和能被 K 整除的最少操作次數二、3513. 不同 XOR 三元組的數目 I三、3514. 不同 XOR 三元組的數目 II四、3515. 帶權樹中的最短路徑 一、3512. 使數組和能被 K 整除的最少操作次數 題目鏈接 本題實際上求的就是數組 nums 和的余數&#xff0c;代碼如下&…

【后端】【python】利用反射器----動態設置裝飾器

&#x1f4d8; Python 裝飾器進階指南 一、裝飾器本質 ? 本質概念 Python 裝飾器的本質是 函數嵌套 返回函數&#xff0c;它是對已有函數的增強&#xff0c;不修改原函數代碼&#xff0c;使用語法糖 decorator 實現包裹效果。 def my_decorator(func):def wrapper(*args, …

Nodejs Express框架

參考&#xff1a;Node.js Express 框架 | 菜鳥教程 第一個 Express 框架實例 接下來我們使用 Express 框架來輸出 "Hello World"。 以下實例中我們引入了 express 模塊&#xff0c;并在客戶端發起請求后&#xff0c;響應 "Hello World" 字符串。 創建 e…

Docker Swarm 集群

Docker Swarm 集群 本文檔介紹了 Docker Swarm 集群的基本概念、工作原理以及相關命令使用示例&#xff0c;包括如何在服務調度中使用自定義標簽。本文檔適用于需要管理和擴展 Docker 容器化應用程序的生產環境場景。 1. 什么是 Docker Swarm Docker Swarm 是用于管理 Docker…

充電寶項目中的MQTT(輕量高效的物聯網通信協議)

文章目錄 補充&#xff1a;HTTP協議MQTT協議MQTT的核心特性MQTT vs HTTP&#xff1a;關鍵對比 EMQX項目集成EMQX集成配置客戶端和回調方法具體接口和方法處理處理類 補充&#xff1a;HTTP協議 HTTP是一種應用層協議&#xff0c;使用TCP作為傳輸層協議&#xff0c;默認端口是80…

【iOS】UIPageViewController學習

UIPageViewController學習 前言創建一個UIPageViewController最簡單的使用 UIPageViewController的方法說明&#xff1a;效果展示 UIPageViewController的協議方法 前言 筆者最近在寫項目時想實現一個翻書效果&#xff0c;上網學習到了UIPageViewController今天寫本篇博客總結…

Linux搭建環境:從零開始掌握基礎操作(四)

? ? 您好&#xff0c;我是程序員小羊&#xff01; 前言 軟件測試第一步就是搭建測試環境&#xff0c;如何搭建好測試環境&#xff0c;需要具備兩項的基礎知識&#xff1a; 1、Linux 命令: 軟件測試第一個任務, 一般都需要進行環境搭建, 一部分&#xff0c;環境搭建內容是在服…

一天一個java知識點----Tomcat與Servlet

認識BS架構 靜態資源&#xff1a;服務器上存儲的不會改變的數據&#xff0c;通常不會根據用戶的請求而變化。比如&#xff1a;HTML、CSS、JS、圖片、視頻等(負責頁面展示) 動態資源&#xff1a;服務器端根據用戶請求和其他數據動態生成的&#xff0c;內容可能會在每次請求時都…

YOLOV8 OBB 海思3516訓練流程

YOLOV8 OBB 海思3516訓練流程 目錄 1、 下載帶GPU版本的torch(可選) 1 2、 安裝 ultralytics 2 3、 下載pycharm 社區版 2 4、安裝pycharm 3 5、新建pycharm 工程 3 6、 添加conda 環境 4 7、 訓練代碼 5 9、配置Ymal 文件 6 10、修改網絡結構 9 11、運行train.py 開始訓練模…

【深度學習】花書第18章——配分函數

直面配分函數 許多概率模型&#xff08;通常是無向圖模型&#xff09;由一個未歸一化的概率分布 p ~ ( x , θ ) \tilde p(\mathbf x,\theta) p~?(x,θ)定義。我們必須通過除以配分函數 Z ( θ ) Z(\pmb{ \theta}) Z(θ)來歸一化 p ~ \tilde p p~?。以獲得一個有效的概率分…

工作記錄1

日常總結、靈感記錄、學習要點。持續記錄 學海無涯,再好的記性也比不過爛筆頭,記錄一下學習日常、靈感、要點。 前言:最近看見一個博文,很有感觸,是某個大佬自己運營的網站,分享了他的各種經驗文章和自身的一些筆記。本人還沒有他這么屌,所以還是先在CSDN上小試牛刀吧…

Spring Boot(二十一):RedisTemplate的String和Hash類型操作

RedisTemplate和StringRedisTemplate的系列文章詳見&#xff1a; Spring Boot&#xff08;十七&#xff09;&#xff1a;集成和使用Redis Spring Boot&#xff08;十八&#xff09;&#xff1a;RedisTemplate和StringRedisTemplate Spring Boot&#xff08;十九&#xff09;…

智能指針之設計模式1

本文探討一下智能指針和GOF設計模式的關系&#xff0c;如果按照設計模式的背后思想來分析&#xff0c;可以發現圍繞智能指針的設計和實現有設計模式的一些思想體現。當然&#xff0c;它們也不是嚴格意義上面向對象的設計模式&#xff0c;畢竟它們沒有那么分明的類層次體系&…

中間件--ClickHouse-1--基礎介紹(列式存儲,MPP架構,分布式計算,SQL支持,向量化執行,億萬級數據秒級查詢)

1、概述 ClickHouse是一個用于聯機分析(OLAP)的列式數據庫管理系統(DBMS)。它由俄羅斯的互聯網巨頭Yandex為解決其內部數據分析需求而開發&#xff0c;并于2016年開源。專為大規模數據分析&#xff0c;實時數據分析和復雜查詢設計&#xff0c;具有高性能、實時數據和可擴展性等…

Go之Slice和數組:深入理解底層設計與最佳實踐

在Go語言中&#xff0c;數組&#xff08;Array&#xff09;和切片&#xff08;Slice&#xff09;是兩種看似相似卻本質不同的數據結構。本文將深入剖析它們的底層實現機制&#xff0c;并結合實際代碼示例&#xff0c;幫助開發者掌握核心差異和使用場景。 一、基礎概念&#xff…

力扣熱題100——普通數組(不普通)

普通數組但一點不普通&#xff01; 最大子數組和合并區間輪轉數組除自身以外數組的乘積缺失的第一個正數 最大子數組和 這道題是非常經典的適用動態規劃解決題目&#xff0c;但同時這里給出兩種解法 動態規劃、分治法 那么動態規劃方法大家可以在我的另外一篇博客總結中看到&am…

矩陣基礎+矩陣轉置+矩陣乘法+行列式與逆矩陣

GPU渲染過程 矩陣 什么是矩陣&#xff08;Matrix&#xff09; 向量 &#xff08;3&#xff0c;9&#xff0c;88&#xff09; 點乘&#xff1a;計算向量夾角 叉乘&#xff1a;計算兩個向量構成平面的法向量。 矩陣 矩陣有3行&#xff0c;2列&#xff0c;所以表示為M32 獲取固…

MySQL之text字段詳細分類說明

在 MySQL 中&#xff0c;TEXT 是用來存儲大量文本數據的數據類型。TEXT 類型可以存儲非常長的字符串&#xff0c;比 VARCHAR 類型更適合存儲大塊的文本數據。TEXT 數據類型分為以下幾個子類型&#xff0c;每個子類型用于存儲不同大小范圍的文本數據&#xff1a; TINYTEXT: 可以…

超詳細!Android 面試題大匯總與深度解析

一、Java 與 Kotlin 基礎 1. Java 的多態是如何實現的&#xff1f; 多態是指在 Java 中&#xff0c;同一個行為具有多個不同表現形式或形態的能力。它主要通過方法重載&#xff08;Overloading&#xff09;和方法重寫&#xff08;Overriding&#xff09;來實現。 方法重載&a…

如何提高webrtc操作跟手時間,降低延遲

第一次做webrtc項目&#xff0c;操作延遲&#xff0c;一直是個問題&#xff0c;多次調試都不能達到理想效果。偶爾發現提高jitterBuffer時間可以解決此問題。關鍵代碼 const _setJitter (values: number) > { const receives peerConnection.getReceivers();receives.f…