CountDownLatch的理解和使用 多線程同步器

CountDownLatch的理解和使用

在筆者想要了解Thrift時候,找到一個博主寫的系統間通信技術的架構設計,在了解和學習的過程中遇到很多小問題和基礎知識,自己還是不夠清楚,就查詢和總結下。

因為筆者也都是從網上找的一些資料,好的資料筆者都是自己收敲一遍,這樣覺得能夠加深下印象,引發更多的思考,畢竟很多時候筆者感覺自己都是七秒的記憶。

在第一篇文章中遇到了一個CountDownLatch同步計數器,當計數器數值減為0時,所有受其影響而等待的線程將會被激活,這樣保證模擬并發請求的真實性。

CountDownLatch概念

CountDownLatch是一個同步工具類,用來協調多個線程之間的同步,或者說起到線程之間的通信(而不是用作互斥的作用)。

CountDownLatch能夠使一個線程在等待另外一些線程完成各自工作之后,再繼續執行。使用一個計數器進行實現。計數器初始值為線程的數量。當每一個線程完成自己任務后,計數器的值就會減一。當計數器的值為0時,表示所有的線程都已經完成一些任務,然后在CountDownLatch上等待的線程就可以恢復執行接下來的任務。

CountDownLatch的用法

CountDownLatch典型用法:1、某一線程在開始運行前等待n個線程執行完畢。將CountDownLatch的計數器初始化為new CountDownLatch(n),每當一個任務線程執行完畢,就將計數器減1 countdownLatch.countDown(),當計數器的值變為0時,在CountDownLatch上await()的線程就會被喚醒。一個典型應用場景就是啟動一個服務時,主線程需要等待多個組件加載完畢,之后再繼續執行。

CountDownLatch典型用法:2、實現多個線程開始執行任務的最大并行性。注意是并行性,不是并發,強調的是多個線程在某一時刻同時開始執行。類似于賽跑,將多個線程放到起點,等待發令槍響,然后同時開跑。做法是初始化一個共享的CountDownLatch(1),將其計算器初始化為1,多個線程在開始執行任務前首先countdownlatch.await(),當主線程調用countDown()時,計數器變為0,多個線程同時被喚醒。

CountDownLatch的不足

CountDownLatch是一次性的,計算器的值只能在構造方法中初始化一次,之后沒有任何機制再次對其設置值,當CountDownLatch使用完畢后,它不能再次被使用。

?

CountDownLatch(倒計時計算器)使用說明

方法說明

public void countDown()

  遞減鎖存器的計數,如果計數到達零,則釋放所有等待的線程。如果當前計數大于零,則將計數減少.

public boolean await(long timeout,TimeUnit unit) throws InterruptedException

  使當前線程在鎖存器倒計數至零之前一直等待,除非線程被中斷或超出了指定的等待時間。如果當前計數為零,則此方法立刻返回true值。

  如果當前計數大于零,則出于線程調度目的,將禁用當前線程,且在發生以下三種情況之一前,該線程將一直出于休眠狀態:

  由于調用countDown()方法,計數到達零;或者其他某個線程中斷當前線程;或者已超出指定的等待時間。

  • 如果計數到達零,則該方法返回true值。
  • 如果當前線程,在進入此方法時已經設置了該線程的中斷狀態;或者在等待時被中斷,則拋出InterruptedException,并且清除當前線程的已中斷狀態。
  • 如果超出了指定的等待時間,則返回值為false。如果該時間小于等于零,則該方法根本不會等待。

參數:

  timeout-要等待的最長時間

  unit-timeout 參數的時間單位

返回:

  如果計數到達零,則返回true;如果在計數到達零之前超過了等待時間,則返回false

拋出:

  InterruptedException-如果當前線程在等待時被中斷

例子1:

  主線程等待子線程執行完成在執行

?

package com.example.demo.CountDownLatchDemo;import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** 主線程等待子線程執行完成再執行*/
public class CountdownLatchTest1 {public static void main(String[] args) {ExecutorService service = Executors.newFixedThreadPool(3);final CountDownLatch latch = new CountDownLatch(3);for (int i = 0; i < 3; i++) {Runnable runnable = new Runnable() {@Overridepublic void run() {try {System.out.println("子線程" + Thread.currentThread().getName() + "開始執行");Thread.sleep((long) (Math.random() * 10000));System.out.println("子線程"+Thread.currentThread().getName()+"執行完成");latch.countDown();//當前線程調用此方法,則計數減一} catch (InterruptedException e) {e.printStackTrace();}}};service.execute(runnable);}try {System.out.println("主線程"+Thread.currentThread().getName()+"等待子線程執行完成...");latch.await();//阻塞當前線程,直到計數器的值為0System.out.println("主線程"+Thread.currentThread().getName()+"開始執行...");} catch (InterruptedException e) {e.printStackTrace();}}
}

?

例子2:

  百米賽跑,4名運動員選手到達場地等待裁判口令,裁判一聲口令,選手聽到后同時起跑,當所有選手到達終點,裁判進行匯總排名

?

package com.example.demo.CountDownLatchDemo;import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class CountdownLatchTest2 {public static void main(String[] args) {ExecutorService service = Executors.newCachedThreadPool();final CountDownLatch cdOrder = new CountDownLatch(1);final CountDownLatch cdAnswer = new CountDownLatch(4);for (int i = 0; i < 4; i++) {Runnable runnable = new Runnable() {@Overridepublic void run() {try {System.out.println("選手" + Thread.currentThread().getName() + "正在等待裁判發布口令");cdOrder.await();System.out.println("選手" + Thread.currentThread().getName() + "已接受裁判口令");Thread.sleep((long) (Math.random() * 10000));System.out.println("選手" + Thread.currentThread().getName() + "到達終點");cdAnswer.countDown();} catch (InterruptedException e) {e.printStackTrace();}}};service.execute(runnable);}try {Thread.sleep((long) (Math.random() * 10000));System.out.println("裁判"+Thread.currentThread().getName()+"即將發布口令");cdOrder.countDown();System.out.println("裁判"+Thread.currentThread().getName()+"已發送口令,正在等待所有選手到達終點");cdAnswer.await();System.out.println("所有選手都到達終點");System.out.println("裁判"+Thread.currentThread().getName()+"匯總成績排名");} catch (InterruptedException e) {e.printStackTrace();}service.shutdown();}
}

?

?原文鏈接:?https://blog.csdn.net/joenqc/article/details/76794356

     ? https://www.cnblogs.com/tstd/p/4987935.html

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

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

相關文章

數據庫操作DDL

show database; 查看所有數據庫 drop database db_name; 刪除數據庫 create database db_name;創建數據庫 一個數據庫對應一個文件夾 create database if not exists db_name; show warnings; 查看所有警告 show create databae db_name;查看創建的數據庫 create database if n…

細數Android開發者的艱辛歷程,已拿offer附真題解析

籠統來說&#xff0c;中年程序員容易被淘汰的原因其實不外乎三點。 1、輸出能力已到頂點。這個人奮斗十來年了&#xff0c;依舊碌碌無為&#xff0c;很明顯這人的天花板就這樣了&#xff0c;說白了&#xff0c;天賦就這樣。 2、適應能力越來越差。年紀大&#xff0c;有家庭&…

原子操作類AtomicInteger詳解

為什么需要AtomicInteger原子操作類&#xff1f; 對于Java中的運算操作&#xff0c;例如自增或自減&#xff0c;若沒有進行額外的同步操作&#xff0c;在多線程環境下就是線程不安全的。num解析為numnum1&#xff0c;明顯&#xff0c;這個操作不具備原子性&#xff0c;多線程并…

移動端Rem之講解總結

日媽常說的H5頁面&#xff0c;為啥叫H5頁面嘛&#xff0c;不就是手機上展示的頁面嗎&#xff1f;那是因為啊手機兼容所有html5新特性&#xff0c;所以跑在手機上的頁面也叫h5頁面&#xff0c;跨平臺&#xff08;安裝ios),基于webview&#xff0c;它就是終端開發的一個組件&…

終于有人把安卓程序員必學知識點全整理出來了,送大廠面經一份!

除了Bug&#xff0c;最讓你頭疼的問題是什么&#xff1f;單身&#xff1f;禿頭&#xff1f;996?面試造火箭&#xff0c;工作擰螺絲&#xff1f; 作為安卓開發者&#xff0c;除了Bug&#xff0c;經常會碰到下面這些問題&#xff1a; 應用卡頓&#xff0c;丟幀&#xff0c;屏幕畫…

ABA問題

CAS&#xff1a;對于內存中的某一個值V&#xff0c;提供一個舊值A和一個新值B。如果提供的舊值V和A相等就把B寫入V。這個過程是原子性的。 CAS執行結果要么成功要么失敗&#xff0c;對于失敗的情形下一班采用不斷重試。或者放棄。 ABA&#xff1a;如果另一個線程修改V值假設原…

mq引入以后的缺點

系統可用性降低? 一旦mq不能使用以后,系統A不能發送消息到mq,系統BCD無法從mq中獲取到消息.整個系統就崩潰了. 如何解決: 系統復雜程度增加? 加入mq以后,mq引入來的問題很多,然后導致系統的復雜程度增加. 如何解決 系統的一致性降低? 有人給系統A發送了一個請求,本來這個請求…

網易云的朋友給我這份339頁的Android面經,成功入職阿里

IT行業的前景 近幾年來&#xff0c;大數據、人工智能AI、物聯網等一些技術不斷發展&#xff0c;也讓人們看到了IT行業的繁榮與良好的前景。越來越多的高校學府加大了對計算機的投入&#xff0c;設立相應的熱門專業來吸引招生。當然也有越來越多的人選擇從事這個行業&#xff0…

AQS相關邏輯解析

關心QPS TPS 如何讓線程停留在lock 1、競爭鎖-(拿到鎖的線程、沒拿到鎖的線程) 臨界區的資源&#xff08;static redis 數據庫變量 配置中心config zookeeper&#xff09;大家共享都可以獲得的資源 臨界區沒拿到鎖的未拿到鎖線程進行停留 2、怎么讓線程停留在Lock方法里 …

git介紹和常用操作

轉載于:https://www.cnblogs.com/kesz/p/11124423.html

網易云的朋友給我這份339頁的Android面經,滿滿干貨指導

想要成為一名優秀的Android開發&#xff0c;你需要一份完備的知識體系&#xff0c;在這里&#xff0c;讓我們一起成長為自己所想的那樣~。 25%的面試官會在頭5分鐘內決定面試的結果60%的面試官會在頭15分鐘內決定面試的結果 一般來說&#xff0c;一場單面的時間在30分鐘左右&…

synchronized 和Lock區別

synchronized實現原理 Java中每一個對象都可以作為鎖&#xff0c;這是synchronized實現同步的基礎&#xff1a; 普通同步方法&#xff0c;鎖是當前實例對象靜態同步方法&#xff0c;鎖是當前類的class對象同步方法塊&#xff0c;鎖是括號里面的對象 當一個線程訪問同步代碼塊…

美團安卓面試,難道Android真的涼了?快來收藏!

我所接觸的Android開發者&#xff0c;百分之九十五以上 都遇到了以下幾點致命弱點&#xff01; 如果這些問題也是阻止你升職加薪&#xff0c;跳槽大廠的阻礙。 那么我確信可以幫你突破瓶頸&#xff01; 1.開發者的門越來越高&#xff1a; 小廠的機會少了&#xff0c;大廠…

django -- 實現ORM登錄

前戲 上篇文章寫了一個簡單的登錄頁面&#xff0c;那我們可不可以實現一個簡單的登錄功能呢&#xff1f;如果登錄成功&#xff0c;給返回一個頁面&#xff0c;失敗給出錯誤的提示呢&#xff1f; 在之前學HTML的時候&#xff0c;我們知道&#xff0c;網頁在往服務器提交數據的時…

美團點評APP在移動網絡性能優化的實踐,通用流行框架大全

" 對于程序員來說&#xff0c;如果哪一天開始他停止了學習&#xff0c;那么他的職業生涯便開始宣告消亡。” 高薪的IT行業是眾多年輕人的職業夢想&#xff0c;然而&#xff0c;一旦身入其中卻發覺沒有想像中那么美好。被稱為IT藍領的編程員&#xff0c;工作強度大&#xf…

java 8大happen-before原則超全面詳解

再來重復下八大原則&#xff1a; 單線程happen-before原則&#xff1a;在同一個線程中&#xff0c;書寫在前面的操作happen-before后面的操作。鎖的happen-before原則&#xff1a;同一個鎖的unlock操作happen-before此鎖的lock操作。volatile的happen-before原則&#xff1a;對…

centos7.0利用yum快速安裝mysql8.0

我這里直接使用MySQL Yum存儲庫的方式快速安裝&#xff1a; 抽象 MySQL Yum存儲庫提供用于在Linux平臺上安裝MySQL服務器&#xff0c;客戶端和其他組件的RPM包。這些軟件包還可以升級和替換從Linux發行版本機軟件存儲庫安裝的任何第三方MySQL軟件包&#xff0c;如果可以從MySQL…

騰訊3輪面試都問了Android事件分發,論程序員成長的正確姿勢

前言 這些題目是網友去美團等一線互聯網公司面試被問到的題目。筆者從自身面試經歷、各大網絡社交技術平臺搜集整理而成&#xff0c;熟悉本文中列出的知識點會大大增加通過前兩輪技術面試的幾率。 主要分為以下幾部分&#xff1a; &#xff08;1&#xff09;Android面試題 …

happens-before規則和as-if-serial語義

概述 本文大部分整理自《Java并發編程的藝術》&#xff0c;溫故而知新&#xff0c;加深對基礎的理解程度。 指令序列的重排序 我們在編寫代碼的時候&#xff0c;通常自上而下編寫&#xff0c;那么希望執行的順序&#xff0c;理論上也是逐步串行執行&#xff0c;但是為了提高…

安裝nodejs

1.安裝nodejs&#xff1a;node-v8.12.0-x64.msi; 2.檢測是否安裝成功&#xff1a; 3.地址欄打開命令行:輸入 cmd回車 4.檢測node是否安裝成功&#xff1a;node -v 看到版本號就是安裝成功了 5.檢測npm是否成功:npm -v 是安裝成功了 6、如果npm成功了&#xff0c;把 package.js…