多线程杀手锏---countDownLatch&&CyclicBarrier

DEM数据下载,拼接,裁剪 目录: 1、数字高程模型(DEM)的数据下载 2、在ENVI里面进行拼接,生成SARscape标准格式的DEM数据3、在ArcGIS里面安装已有的矢量范文,进行掩膜裁剪 4、注意事项 数字高程模型的数据下载: 网址:http://dwtkns.com/srtm30m/ 1.对研究区域进行经纬度选择,然后进行选择下载即可 2.下载的数据是.hgt格式的,按照不同的需求进行转换,这里我是用于ENVI处理,且下载了四个,所有进行了拼接,拼接、格式转换如下 注:可能有时候需要登陆注册,点击下... 阅读详情

多线程是我们学习路上必不可少的一块拦路石,撬开这块石头,就需要掌握好JUC。JUC下的一些并发同步特性在之前的文章里也写过,具体如下:
多线程基础知识

什么是JMM以及volatile的特性
详谈CAS以及ABA问题

线程池以及阻塞队列

AQS的了解,对于AQS是一个比较重要的知识点,下面这几篇文章可以帮助你通俗易懂的了解AQS是如何在底层执行工作的
谈谈你对AQS的了解

AQS的核心原理分析

Java 并发高频面试题:聊聊你对 AQS 的理解?

总的来说AQS在并发里相当于人的大脑,里边一个state,一个当前得锁的线程,一个FIFO的阻塞队列就把线程的安全解决了,

然后接下来说今天的主题 多线程下countDownLatch和CyclicBarrier是如何并发执行,以及它们之间的区别:
CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同;另外,CountDownLatch是不能够重用的,而CyclicBarrier是可以重用的
在这里插入图片描述在这里插入图片描述看完后你会发现CountDownLatch和CyclicBarrier两者的await方法是会阻塞当前线程的,因此如果在线程池中使用CyclicBarrier,如果线程池的core大小小于parties,线程池中的线程遍一直处于阻塞状态,相反CountDownLatch的countDown()在执行后,完美退出当前线程,但是在开启调用CountDownLatch.await()的时候,需要在子线程中,否则就阻塞了当前线程。

上面的如果看的不太了解,则可以看看接下来的这两个具体代码对比:

CyclicBarrier:

1、CyclicBarrier:一个同步辅助类,用于协调多个子线程,让多个子线程在这个屏障前等待,直到所有子线程都到达了这个屏障时,再一起继续执行后面的动作。

2、使用场景举例:
年末公司组织团建,要求每一位员工周六上午8点【自驾车】到公司门口集合,然后【自驾车】前往目的地。
在这个案例中,公司作为主线程,员工作为子线程。

package com.test.spring.support;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/** 
 * @author  javaloveiphone
 * @date 创建时间:2017年1月25日 上午10:59:11 
 * @Description: 
 */
public class Company {
    public static void main(String[] args) throws InterruptedException {

        //员工数量
        int count = 5;
        //创建计数器
        CyclicBarrier barrier = new CyclicBarrier(count+1);

        //创建线程池,可以通过以下方式创建
        //ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1,1,60,TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>(count));
        ExecutorService threadPool =  Executors.newFixedThreadPool(count);

        System.out.println("公司发送通知,每一位员工在周六早上8点【自驾车】到公司大门口集合");
        for(int i =0;i<count ;i++){
            //将子线程添加进线程池执行
            threadPool.execute(new Employee(barrier,i+1));
            Thread.sleep(10);
        }
        try {
            //阻塞当前线程,直到所有员工到达公司大门口之后才执行
            barrier.await();
            Thread.sleep(10);
            // 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。
            //latch.await(long timeout, TimeUnit unit)
            System.out.println("所有员工已经到达公司大门口,公司领导一并【自驾车】同员工前往活动目的地。");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }finally{
            //最后关闭线程池,但执行以前提交的任务,不接受新任务
            threadPool.shutdown();
            //关闭线程池,停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。
            //threadPool.shutdownNow();
        }
    }
}

//分布式工作线程
class Employee implements Runnable{

    private CyclicBarrier barrier;
    private int employeeIndex;

    public Employee(CyclicBarrier barrier,int employeeIndex){
        this.barrier = barrier;
        this.employeeIndex = employeeIndex;
    }

    @Override
    public void run() {
        try {
            System.out.println("员工:"+employeeIndex+",正在前往公司大门口集合...");
            Thread.sleep(10*employeeIndex);
            System.out.println("员工:"+employeeIndex+",已到达。");
            barrier.await();
            Thread.sleep(10);
            System.out.println("员工:"+employeeIndex+",【自驾车】前往目的地");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述子线程执行了await()方法,必须等待其它所有子线程执行await()方法之后,才能一起继续后续的(await后main的)工作,就像上面的例子,所有自驾车必须都到达公司大门口之后,才能一起继续各自自驾车前往目的地。
但,主线程await()之后的工作与子线程await()之后的工作是不受影响的,只要所有的子线程执行了await()方法,主线程此时就可以后续的工作了,不必管子线程await()方法后续工作的情况。

可以看到的是只要都到达了屏障以后,各自执行自己,并不按照之前到达的顺序执行。

CountDownLatch

1、CountDownLatch:一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行。

2、ThreadPoolExecutor/ExecutorService:线程池,使用线程池可以复用线程,降低频繁创建线程造成的性能消耗,同时对线程的创建、启动、停止、销毁等操作更简便。

3、使用场景举例:
年末公司组织团建,要求每一位员工周六上午8点到公司门口集合,统一乘坐公司所租大巴前往目的地。
在这个案例中,公司作为主线程,员工作为子线程。

package com.test.thread;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/** 
 * @author  javaloveiphone
 * @date 创建时间:2017年1月25日 上午10:59:11 
 * @Description: 
 */
public class Company {
    public static void main(String[] args) throws InterruptedException {

        //员工数量
        int count = 5;
        //创建计数器
        //构造参数传入的数量值代表的是latch.countDown()调用的次数
        CountDownLatch latch = new CountDownLatch(count);

        //创建线程池,可以通过以下方式创建
        //ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1,1,60,TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>(count));
        ExecutorService threadPool =  Executors.newFixedThreadPool(count);

        System.out.println("公司发送通知,每一位员工在周六早上8点到公司大门口集合");
        for(int i =0;i<count ;i++){
            //将子线程添加进线程池执行
            Thread.sleep(10);
            threadPool.execute(new Employee(latch,i+1));
        }
        try {
            //阻塞当前线程,直到所有员工到达公司大门口之后才执行
            latch.await();
            // 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。
            //latch.await(long timeout, TimeUnit unit)
            System.out.println("所有员工已经到达公司大门口,大巴车发动,前往活动目的地。");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            //最后关闭线程池,但执行以前提交的任务,不接受新任务
            threadPool.shutdown();
            //关闭线程池,停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。
            //threadPool.shutdownNow();
        }
    }
}

//分布式工作线程
class Employee implements Runnable{

    private CountDownLatch latch;
    private int employeeIndex;

    public Employee(CountDownLatch latch,int employeeIndex){
        this.latch = latch;
        this.employeeIndex = employeeIndex;
    }

    @Override
    public void run() {
        try {
            System.out.println("员工:"+employeeIndex+",正在前往公司大门口集合...");
            Thread.sleep(10);
            System.out.println("员工:"+employeeIndex+",已到达。");
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            //当前计算工作已结束,计数器减一
            latch.countDown();  
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //执行coutDown()之后,继续执行自己的工作,不受主线程的影响
            System.out.println("员工:"+employeeIndex+",吃饭、喝水、拍照。");
        }
    }
}

在这里插入图片描述每一个员工到达之后,执行countDown()方法,直到所有员工到达之后,计数器为0,主线程才会继续执行。

但子线程执行了countDown()方法,之后会继续自己的工作,比如上面的【吃饭、喝水、拍照】,是不受主线程是否阻塞、其它线程是否已经执行countDown()方法的影响的。

CyclicBarrier与CountDownLatch的区别:

1)、构造两者对象传入的参数不一样:构造CyclicBarrier比构造CountDownLatch的参数大了1,原因是构造CyclicBarrier的数量表示的是调用await()的次数,构造CountDownLatch的数量表示的是调用countDown()的次数;

2)、子线程调用了barrier.await()之后,必须等待所有子线程都完成barrier.await()调用后才能一起继续后续自己的工作,而子线程调用latch.countDown()之后,会继续子线程自己的工作,不用等待其它子线程latch.countDown()调用情况。

3)、CyclicBarrier可以循环使用,而CountDownLatch不是循环使用的。

通俗一点就是:
countDownLatch 类似于学校的 4*100接力赛;一共count为4次(4圈),当一个人跑完以后,他就可以休息,喝水了(继续执行子线程),其他人也一样,等所有人都跑完以后,count=0了,裁判宣布结果(main线程)。

CyclicBarrier:有一天同学们上课了,班里老师来的早,等待着那些同学陆陆续续的到来。老师讲课(main线程),同学们听课,记笔记(子线程)。同学们还没有来全,老师不能讲课(main线程被阻塞了),其他在教室的学生也不能记笔记,因为老师还没开始讲呢(子线程在屏障前等待),当所有人都到了以后,开始各干各的,老师讲课,他们在下边记笔记,传纸条等等等。互不打扰。

再说一下谷歌插件的ListeningExecutorService的使用方法

由于普通的线程池,返回的Future,功能比较单一;Guava 定义了 ListenableFuture接口并继承了JDK concurrent包下的Future 接口,ListenableFuture 允许你注册回调方法(callbacks),在运算(多线程执行)完成的时候进行调用。

1.使用方法如下:

1.创建线程池
2.装饰线程池
3.任务处理
4.回调函数处理
5.所有任务完成后处理

会执行回调方法, 执行成功的,执行不成功的都走方法
在这里插入图片描述执行成功截图:

在这里插入图片描述

将等待失效时间修改如下:
在这里插入图片描述
线程池等待5秒,五秒后自动结束里面的线程。
在这里插入图片描述执行了shutdownNow方法,正在执行的被中断了,未被执行的因为本例是基础的Callable所有没能接收返回的Runnable线程,线程继承Runnable可以接收返回的未被执行的那些线程。

上述案例的全部代码如下:

在这里插入图片描述

pom依赖

 <dependencies>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>18.0</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.15</version>
        </dependency>
        
    </dependencies>


import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Callable;

/**
 * @author Shuyu.Wang
 * @package:com.ganinfo.test
 * @className:
 * @description:
 * @date 2018-10-28 19:35
 **/
public class AuthCallable implements Callable {

    private AuthType authType;
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    @Override
    public Object call() throws Exception {
        if ("1".equals(authType.getType())){
            System.out.println("方式一"+authType.getName()+"授权start");
            Thread.sleep(8000);
            System.out.println("方式一授权end");
            return authType.getName();
        }
        if ("2".equals(authType.getType())){
            System.out.println("方式二"+authType.getName()+"授权start");
            Thread.sleep(7000);
            System.out.println("方式二授权end");
            return authType.getName();
        }
        if ("3".equals(authType.getType())){
            System.out.println("方式三"+authType.getName()+"授权start");
            Thread.sleep(5000);
            System.out.println("方式三授权end");
            return authType.getName();
        }
        if ("4".equals(authType.getType())){
            System.out.println("方式四"+authType.getName()+"授权start");
            Thread.sleep(3000);
            System.out.println("方式四授权end");
            return authType.getName();
        }
        if ("5".equals(authType.getType())){
            System.out.println("方式五"+authType.getName()+"授权start");
            Thread.sleep(1000);
            System.out.println("方式五授权end");
            return authType.getName();
        }
        return null;
    }

    public void setAuthType(AuthType authType) {
        this.authType = authType;
    }
}

import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author Shuyu.Wang
 * @package:com.ganinfo.test
 * @className:
 * @description:
 * @date 2018-10-28 19:41
 **/
public class AuthService {
    public static void main(String[] args) {
            long start=System.currentTimeMillis();
            final List<String> list = new ArrayList<>();
            int count=5;
            try {
                final CountDownLatch countDownLatch = new CountDownLatch(count);
                ExecutorService executorService = Executors.newFixedThreadPool(8);
                ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(executorService);
                for (int i = 1; i <= count; i++) {
                    AuthCallable authCallable = new AuthCallable();
                    AuthType authType = new AuthType();
                    authType.setType(String.valueOf(i));
                    authType.setName(String.valueOf(i) + "名称");
                    authCallable.setAuthType(authType);
                    ListenableFuture listenableFuture = listeningExecutorService.submit(authCallable);
                    Futures.addCallback(listenableFuture, new FutureCallback<String>() {
                        @Override
                        public void onSuccess(String name) {
                            System.out.println("授权结果" + name);
                            list.add(name);
                            countDownLatch.countDown();
                        }
                        @Override
                        public void onFailure(Throwable throwable) {
                            countDownLatch.countDown();
                            System.out.println("处理出错:"+throwable);
                        }
                    });
                }
                try {
                    executorService.shutdown();
                    //shutdown调用后,不可以再submit新的task,已经submit的将继续执行。
                    if (!countDownLatch.await(5, TimeUnit.MINUTES)) {
                        System.out.println("超时的时候向线程池中所有的线程发出中断");
                        // 超时的时候向线程池中所有的线程发出中断(interrupted)。
                        executorService.shutdownNow();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    //shutdownNow试图停止当前正执行的task,并返回尚未执行的task的list
                    //由于本例中继承的是Callable,所以无法接收返回的Runable接口
                    List<Runnable> listRun =executorService.shutdownNow();
                }
                System.out.println("执行结果" + list.toString());
                long end=System.currentTimeMillis();
                System.out.println("用时" + (end-start));
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
}

import lombok.Data;

/**
 * @author Shuyu.Wang
 * @package:com.ganinfo.test
 * @className:
 * @description:
 * @date 2018-10-28 19:34
 **/
@Data
public class AuthType {
    private String type;
    private String name;
}

一句话说明白shutdown和shutdownNow的区别

shutdown只是将线程池的状态设置为SHUTWDOWN状态,正在执行的任务会继续执行下去,没有被执行的则中断。而shutdownNow则是将线程池的状态设置为STOP,正在执行的任务则被停止,没被执行任务的则返回。

参考文章:
Java并发编程–CountDownLatch配合线程池
java多线程CyclicBarrier使用示例,让线程起步走

java多线程CountDownLatch及线程池ThreadPoolExecutor/ExecutorService使用示例

https://blog.youkuaiyun.com/weixin_39800144/article/details/82776523

AutoSAR系列讲解(实践篇)12.1-Diagnostics简介 主要概括性的讲解了诊断协议UDS和AutoSAR的诊断架构 阅读详情

相关推荐

D触发器版图设计的艺术:最小化面积与最大化性能的平衡之道

本文探讨了D触发器版图设计中如何平衡最小化面积与最大化性能的核心挑战。通过分析晶体管布局、互联优化、时钟分布等关键策略,结合先进制程下的功耗与信号完整性考量,为数字IC工程师提供了从基础优化到制造验证的实用解决方案,助力实现高性能、低面积的芯片设计。

aa123的博客 909

CountDownLatch 和 CyclicBarrier的区别与详解

CountDownLatch 的计数器是大于或等于线程数的,而CyclicBarrier是一定等于线程数 CountDownLatch 放行由其他线程控制而CyclicBarrier是由本身来控制的

wgq2020的博客 9316

grafana对接zabbix数据展示

【配置】点击【模板】点击【创建模板】添加三个监控项:【名称】搜索【】创建的模板;点击上方【监控项】,点击创建【监控项】点击上方【触发器】点击【创建触发器】主机关联监控模板:左侧【配置】点击 【主机】点击【Zabbix server】查看:左侧点击【监测】点击【主机】点击【Zabbix server】点击最新数据,找到添加的三个模板主机关联监控模板:左侧【配置】点击 【主机】点击【Zabbix server】把监控模板用起来① 明确获取指标数据的方法。

2401_83883919的博客 6592

多线程并发之CountDownLatch阻塞等待

latch则是门闩、锁住的含义。整体含义可以理解为倒数的门栓。的作用也是如此,在构造的时候需要传入一个整数n(必须>0),在这个整数“倒数”到0之前,主线程需要等待在门口,而这个“倒数”过程则是由各个执行线程驱动的,每个线程执行完一个任务“倒数”一次。总结来说,的作用就是等待其他的线程都执行完任务,必要时可以对各个任务的执行结果进行汇总,然后主线程才继续往下执行。主要有两个方法:和。方法用于使计数器减一,其一般是执行任务的线程调用,方法则使调用该方法的线程处于等待状态,其一般是主线程调用。......

Lifelong learning 7954

YonSuite如何新增用户并分配角色角色授权图文教程

用友YonSuite产品基础教学

ct341688的博客 617

AI代码标注专家Prompt指令的最佳实践

AI代码标注专家 Prompt 可作为项目级别提示词使用,专门负责为 AI 生成的代码添加特定的注释标记,然后基于 Node 脚本可以初步统计出 AI 代码占比。

💻 Code:TypeScript / Engineering 🤖 AI:Prompt Optimization / Context Memory / Coding Agents 612

多线程同步器之CountDownLatch

文章目录CountDownLatch是什么核心方法构造方法常用的其他三个方法使用案例 CountDownLatch是什么 countDownLatch是在java1.5被引入,可以翻译为计数器。主要用于等待多个线程一起执行完成后继续下一步,Thread.join()有点类似 核心方法 构造方法 CountDownLatch 值提供了一个构造方法,传入一个计数器的值 常用的其他三个方法 //调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行 public void await()

念念不忘,必有回响 2260

【AMD | Docker】超级全面版本:在Docker中验证AMD GPU移动显卡可用性的方法

1. 安装ROCm Docker支持 ■AMD GPU驱动 ■ROCM ■Docker 2. 配置Docker使用ROCm 3. 使用官方ROCm Docker镜像 4. 使用Docker CLI参数访问GPU

静谧、淡雅 684

CountDownLatch介绍和使用【Java多线程必备】

CountDownLatch介绍、特性、注意事项、使用案例(干货满满)

Mr.绵羊的知识星球 3万+

Flink实战(101):双流join(三)双流中实现Inner Join、Left Join与Right Join

声明:本系列博客是根据SGG的视频整理而成,非常适合大家入门学习。 《2021年最新版大数据面试题全面开启更新》 简介 之前文章中提到JoinedStream与CoGroupedStream,例如下列代码: dataStream.join(otherStream) .where(0).equalTo(1) .window(TumblingEventTimeWindows.of(Time.seconds(3))) .apply { ... } 由于joinedStream与

微信搜:import_bigdata,大数据领域硬核原创作者 736

微信小程序数据采集实战:抓包+接口分析+动态数据全流程

微信小程序爬虫虽然比普通网页爬虫复杂,但只要掌握了正确的方法,其实并没有想象中那么难。核心思路就是:先绕过证书校验抓包,然后反编译小程序找到加密逻辑,最后用Python模拟相同的加密和解密过程。需要特别提醒的是,本文仅供技术研究使用。请遵守《网络安全法》和相关法律法规,不要爬取他人的敏感数据,不要将爬虫技术用于非法用途。尊重他人的知识产权和数据安全,才能让技术发挥真正的价值。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1091

【线程池】线程同步器CountDownLatch

CountDownLatch的原理和ReentrantLock的原理类似,都是基于AQS实现的。CountDownLatch 用于阻塞当前 1 个或多个线程,其目的是让这些线程等待其它线程的执行完成。可以简单将其理解为一个计数器,当初始化一个 count=n 的 CountDownLatch 对象之后,需要调用该对象的 CountDownLatch#countDown 方法来对计数器进行减值,直到计数器为 0 的时候,等待该计数器的线程才能继续执行。

weixin_44823875的博客 6040

uniapp - 解决苹果ios真机运行报错:错误:请查看是否设备未加入到证书列表或者确认证书类型是否匹配(HbuilderX运行IOS手机出现问题,uniapp运行到IOS真机提示请查看是否设备未)

uni-app,ios苹果,App平台端,uniapp运行到IOS真机提示错误:请查看是否设备未加入到证书列表或者确认证书类型是否匹配,UUID在哪里,uniApp运行到ios真机报错解决,安装自定义基座App失败,没找到有计划资源,证书、标识符和描述文件,证书标识符和描述文件下面没有选项怎么回事,HBuilder真机调试报错请查看是否设备未加入到证书列表或者确认证书类型是否匹配,UniApp运行到IOS真机提示,授权的设备才可以直接安装基座,添加调试的IOS设备,在Devices中,添加手机设备UUID

🏆 前端领域优质创作者 1万+

多线程同步必学:CountDownLatch的核心原理与应用

本文详细介绍了CountDownLatch的原理和使用方法,并提供了一个使用示例和一些应用场景。希望本文能够帮助你更好地理解和使用CountDownLatch。如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

star_nwe的博客 1034

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

大厂高频多线程编程中的CountDownLatch:一种简单高效的同步工具

这个方法会对state值减1,会调用到AQS中releaseShared()方法,目的是为了调用doReleaseShared()方法,这个是AQS定义好的释放资源的方法,而tryReleaseShred()则是子类实现的,可以看到是一个自旋CAS操作,每次都获取state值,如果为0则直接返回,否则就执行减1的操作,失败了就重试,如果减完后值为0就表示要释放所有阻塞的线程了,也就会执行到AQS中的doReleaseShared()方法。调用 await() 方法的线程会被阻塞,直到计数器的值为 0。

zjjcchina的博客 931

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Java并发新利器:CountDownLatch解密,提高线程协同效率!

在并发环境下,很多场景需要一个或多个线程等待其他线程完成特定的任务后再继续执行。CountDownLatch 正是为了应对这类场景而设计的,它能够在多个线程之间建立一种同步机制,使得线程能够协同工作,确保某些任务在所有线程完成后再执行。

wcwmsj的博客 1219

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

CountDownLatch

(门阀、计数器)是多线程控制的一种工具 ,它用来协调各个线程之间的同步。countDownLatch相当于一个计数器,能够使一个线程等待另外一些线程完成各自的工作后,再继续执行。这个计数器的初始值就是线程的数量,每当一个线程完成之后,计数器就进行减1,当计数器的值为0时,那么在countDownLatch上等待的线程就可以继续执行。countDownLatch接收一个int类型的参数,表示要等待的工作线程个数}

爪哇人的博客 1031

多线程之CountDownLatch详解

摘要:Java并发工具类CountDownLatch通过内部计数器机制实现线程同步,允许一个或多个线程等待其他线程完成操作。其核心方法包括await()和countDown(),底层基于AQS框架实现。典型应用场景包括主线程等待子线程完成任务、并行任务协调等。CountDownLatch初始化时设置计数器值,每次countDown()调用递减计数器,当计数器归零时唤醒所有等待线程。源码分析表明其通过CAS操作确保线程安全,并提供超时等待机制增强灵活性。

qq_844085127的博客 916

Java 多线程之 CountDownLatch(计数等待/同步辅助类)

CountDownLatch 是Java中提供的一种同步工具类,用于控制多个线程之间的执行顺序和协调。CountDownLatch 通过一个计数器来实现,该计数器初始化为一个正整数,表示需要等待的线程数目。每个线程执行完一定的任务后,会调用方法将计数器减1。当计数器减到0时,表示所有线程已经完成任务,等待在await()方法处的线程被唤醒,继续执行后续操作。控制执行顺序:控制多个线程执行的顺序,让某个线程等待其他线程完成特定任务后再执行。

QIFU的专栏 2114

线程池(Executors、Future、CountDownLatch、CyclicBarrier)

Executors、Future、CountDownLatch、CyclicBarrier

好记性不如烂笔头 742

以为很熟悉CountDownLatch的使用了,居然在生产环境翻车了

注意上面的那个异常是线程池抛出来的,我们自己也需要将线程池进行try catch,记录问题数据,并且在finally中执行countDownLatch.countDown来避免,线程池的使用

YYniannian的博客 616

CountDownLatch的理解和使用

在笔者想要了解Thrift时候,找到一个博主写的系统间通信技术的架构设计,在了解和学习的过程中遇到很多小问题和基础知识,自己还是不够清楚,就查询和总结下。 因为笔者也都是从网上找的一些资料,好的资料笔者都是自己收敲一遍,这样觉得能够加深下印象,引发更多的思考,毕竟很多时候笔者感觉自己都是七秒的记忆。 在第一篇文章中遇到了一个CountDownLatch同步计数器,当计数器数值减为0时...

weixin_30951231的博客 1293

CountDownLatch、join 与 CyclicBarrier

java中的并发工具类: 1、CountDownLatch: CountDownLatch允许一个或多个线程等待其他线程完成操作。 假如有这样一个需求:我们需要解析一个Excel里多个sheet的数 据,此时可以考虑使用多线程,每个线程解析一个sheet里的数据,等到 所有的sheet都解析完之后,程序需要提示解析完成。在这个需求中,要 实现主线程等待所有线程完成sheet的解析操作,最简单的做法是使用 join()方法,如代码清单: public class JoinCountDownLatchTest

weixin_43902350的博客 245

【多线程】Java并发工具类之CountDownLatch 同步协作的利器

CountDownLatch用一个给定的计数器来初始化,该计数器的值表示需要等待完成的任务数量。当计数器的值达到零时,表示所有需要等待的任务都已经完成,此时在CountDownLatch上等待的线程将被唤醒并可以继续执行。● 其它线程调用countDown方法会将计数器减1(调用countDown方法的线程不会阻塞),当计数器的值变为0时,因await方法阻塞的线程会被唤醒,继续执行。CountDownLatch内部维护了一个计数器,只有当计数器==0时,某些线程才会停止阻塞,开始执行。

qq_39666711的博客 2084

14-1.Java 多线程编程之 CountDownLatch(CountDownLatch 核心功能、CountDownLatch 核心方法、CountDownLatch 实例实操)

14-1.Java 多线程编程之 CountDownLatch(CountDownLatch 核心功能、CountDownLatch 核心方法、CountDownLatch 实例实操)

weixin_52173250的博客 645

容器并发控制

问题描述 设计一个容器,有add和size两个方法,然后有两个线程,一个线程往容器里加10个数,另一个 线程用来控制第一个线程,当加到5个数时,线程停止,让第一个线程继续加数 方法一(Synchronized) 1.解题思路 直接在类里定义一个list,提供add()和size()两个方法。主方法new两个线程t1和t2,当容器数字个数不为5时,t2线程阻塞。这段时间,t1线程不断执行add()方法,当达到5个数后,t1唤醒t2,自己进入阻塞状态。t2被唤醒后,打印“t2停止”,然后又唤醒t1线程,添加

qq_43568109的博客 204
上一篇: mysql的一些知识点
下一篇: 今天谈一些写java项目约定的规范
凌晨里的无聊人
博客等级 码龄8年 2320粉丝 206原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌晨里的无聊人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值