Synchronizer 闭锁(CountDownLatch,FutureTask ) 信号量(Semaphore) 关卡(CyclicBarrier) 知识点总结(java并发编程实践读书笔记三)

CountDownLatch,CyclicBarrier和信号量Semaphore CountDownLatch,CyclicBarrier和信号量Semaphore都是java并发包concurrent下提供的并发工具类,是比synchrorized关键字更高效的同步结构。 CountDownLatch的用法顾名思义有一个计数器的概念,其应用场景是,如果B组线程要等A组线程全部执行完后再执行,那A组中每个线程都会调用其countDown方法计数,即A组中每跑一个线程计数加一。... 阅读详情

Synchronizer

    Synchronizer是一个对象,可以根据本身的状态调整线程的控制流
  • 结构特性:
    • 封装状态,而这些状态决定着线程执行到某一点时是通过还是被迫等待
    • 提供操作状态的方法,以及高效的等待Synchronizer进入到期望状态的方法
      • 理解:第一句话~
                                             就阻塞队列来讲,它封装了 队列已满,队列为空 等状态;
                                             队列为空这个状态决定了消费者从队列中中获取数据时,是顺利获取,还是等待
                                             同样的,队列已满这个状态就决定了生产者生产的数据能不能顺利放到队列中去
                   第二句话~
                                             还没弄明白
  • 包括
    • 阻塞队列 BlockingQueue
    • 信号量 semaphore
    • 关卡 barrier
    • 闭锁 latch

闭锁(latch)

    可以延迟线程的进度,直到闭锁达到终止状态;
    闭锁工作起来就像一道门,在闭锁到达终止状态之前,门是关闭的,没有线程能通过;一旦到达终止状态,门开了,所有线程都能通过,闭锁的状态会一直保持在敞开状态
    可以用来确保特定的活动知道其他活动完成之后才发生
  • 确保一个计算不会执行,直到他需要的资源被初始化
    • 一个二元闭锁(只有两个状态)来表达资源是否已经初始化,所有需要用到该资源的线程都在闭锁中等待
  • 确保一个服务s不会开始,直到他依赖的服务(t1-tn)都已经开始
    • 还不明白怎么回事,大概就是在s中等待t1-tn的闭锁开启
    CountDownLatch -- 一个闭锁的实现
    CountDownLatch通过一个整数实例化对象,该对象每调用一次countDown方法,该整数减一,若该数字为0,则闭锁打开
    示例:
public class TestHarness{
    public long timeTasks(int nThreads, final Runnable task) throws InterruptedException{
        final CountDownLatch startGate = new CountDownLatch(1);//全部线程开始的闭锁
        final CountDownLatch endGate = new CountDownLatch(nThread);//全部线程结束的闭锁
        for(int i = 0 ; i < nThreads ; i++){
            Thread t = new Thread(){
                public void run(){
                    try{
                        startGate.await();//所有的线程都在这里等待闭锁打开
                        try{
                            task.run();//实际要调用的方法
                        }finally{
                            endGate.countDown(); //每一个线程执行完毕,调用countDown()方法,直到全部的线程(nThreads个)执行完毕,闭锁打开
                        }
                    }catch(InterruptedException e){}
                }
            };
            t.start(); //t.start()不会立即开始执行task.run()方法,线程一开始执行startGate.await();会等待闭锁startGate打开
        }
        long start = System.nanoTime();//记录开始时间
        startGate.countDown();//闭锁startGate初始化为1,执行一次countDown()方法,闭锁就打开了,所有的线程可以继续执行
        endGate.await();//当前线程在这里等待所有的线程执行完毕
        long end = System.nonaTIme();//记录结束时间
        return end - start;
    }
}


上面的示例是用来统计 nThread 个线程,从第一个线程启动到全部的线程终止所花费的时间
FutureTask  --另一种闭锁的实现
    描述了一个可以携带结果的计算,通过callable实现的
    有三个状态 等待 运行 完成,完成之后永远停留在这个状态
    
    Future.get() 依赖于任务完成的状态,如果任务完成,则返回结果或者抛出异常。若没有完成,则阻塞直到任务完成,然后返回
 
    为什么说FatureTask是一种闭锁?FutureTask有一个状态标志,即任务是否完成。 线程T1--Tn调用其get()方法,如果状态标志为未完成,会阻塞全部的线程,等于关闭了一道门,所有的线程都过不去了,直到状态标志改为任务完成,才会有返回值,所有的线程继续执行。所以FutureTask类似于一个二元闭锁。。。不知道这样理解对不对~~
    
    使用FutureTask预加载数据
   
 public class Preloader{
        private final FutureTask<ProducInfo> future = new FutureTask<ProductInfo>( new Callable<ProductInfo>(){
                public ProductInfo call() throws DataLoadException{//Callable接受的任务代码中抛出的Throwable会被封装成一个ExecutionException,并被他的调用者future.get()方法重新抛出
                    return loadProductInfo();//比较耗时的加载操作
                }
            }
        );
        
 
        private final Thread thread = new Thread(future);
 
        public void start(){ thread.start();}//这里启动新线程进行预加载工作
 
        public ProductInfo get() throws DataLoadException,InterruptedException{
            try{
                return future.get(); //调用的时候如果FutureTask 的任务完成状态为未完成,则阻塞直到状态改变
            }catch(ExecutionException e){//ExecutionException包含三种情况1.受检查异常;2.RuntimeException;3.Error~必须分别处理
                Throwable cause = e.getCause();
                if(cause instanceof DataLoadException) throw (DataLoadException)cause; //这里处理一下已知的异常
                else throw launderThrowable(cause);    //通过launderThrowable()方法处理其他情况的异常1.如果cause是一个Error,抛出;2.如果是一个RuntimeException,返回该异常;3.其他情况下抛出IllegalStateException
            }
        }
    }

计数信号量(Semaphore)

    用来控制访问某特定资源的活动的数量,或者同时执行某一给定操作的数量。
    例如数据库连接池中数据链接的访问,阻塞队列中的有界队列,等多个线程竞争的有限资源,可以用计数信号量来处理
    
    计数信号量管理一个有效的许可集,许可的初始量通过构造函数传给Semaphore
    acquire方法获取一个许可,如果剩余许可为0,此方法会阻塞直到有可用的许可为止
    release方法释放一个许可
 
    二元信号量(初始值为1的Semaphore)可以用作 互斥 锁。 意思是 -- 谁拥有这唯一的许可,就拥有了互斥锁
    
    示例:有界的阻塞容器,使用信号量来约束容器
   
 public class BoundedHashSet<T>{
        private final Set<T> set;
        private final Semaphore sem;
        //构造方法,初始化边界
        public BoundedHashSet(int bound){
            this.set = Collections.synchronizedSet(new HashSet<T>());
            sem = new Semaphore(bound);//初始化许可集的大小,即该有界阻塞队列的大小
        }
 
        public boolean add(T o) throws InterruptedException{
            sem.acquire();//添加元素时获取一个许可,如果剩余许可为0,则说明此有界阻塞队列已满
            boolean wasAdded = false; //返回值,默认为添加元素失败。
            try{
                wasAdded=set.add(o);//向队列中添加元素,如果成功,则返回成功
                return wasAdded;
            }finally{
                if(!wasAdded) sem.release(); //如果添加失败,把方法一开始获取的许可释放掉
            }
        }
        
        public boolean remove (Object o){
            boolean wasRemoved = set.remove(o);
            if(wasRemoved) sem.release();//如果删除成功,则释放一个许可
            return wasRemoved;
        }
    }

 

关卡(barrier)

    它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。
    一定数量的线程只有都运行到关卡的屏障点时,才会同时继续往下执行。也可以向构造函数传递一个关卡行为,当所有线程成功通过关卡,会在其中一个线程执行事先定义好的关卡行为
    示例(来自jdk文档)
    有一个矩阵 float[][] ,现在对其进行分行并行计算,每个线程计算一行,当全部行计算完毕,即所有的线程都到达一个关卡时,开始汇总计算的结果。
 
class Solver {
   final int N;
   final float[][] data;
   final CyclicBarrier barrier;
   
   class Worker implements Runnable {
     int myRow;
     Worker(int row) { myRow = row; }
     public void run() {
       while (!done()) {
         processRow(myRow); //每一个线程负责处理一行数据

         try {
           barrier.await(); //处理完行数据之后在这个关卡等待其他线程,当所有的线程都处理完毕,才继续向下执行
         } catch (InterruptedException ex) { 
            return; 
         } catch (BrokenBarrierException ex) { 
            return; 
         }
       }
     }
   }

   public Solver(float[][] matrix) {
     data = matrix;
     N = matrix.length;
     barrier = new CyclicBarrier(N, 
                                 new Runnable() {
                                   public void run() { 
                                     mergeRows(...); //汇总计算的结果语句
                                   }//关卡CyclicBarrier 初始化时参数一为:关卡需要等待的线程的数量n,只有当n个线程全部到达此关卡,才能顺利通过;参数二为:一个关卡行为,当关卡顺利通过之后,在一个子任务线程中执行这个行为。Runnable类型~
                                 });
     for (int i = 0; i < N; ++i) 
       new Thread(new Worker(i)).start(); //每一行一个线程处理,分别启动

     waitUntilDone();
   }
}


关卡的实际应用远远没有这么简单,可以看一下jdk文档,线程在关卡处等待的时候会有很多种意外情况,这些都要分别去处理,等把其他地方的知识点也研究过之后在回过够来看这里jdk中的内容吧
 
 
VS2022+Qt6保姆级配置指南:从插件安装到项目互通全流程(附常见错误解决) 本文提供了一份详细的Visual Studio 2022与Qt6集成开发环境配置指南。从插件安装、环境搭建到项目创建与互通,涵盖了全流程操作步骤,并针对常见的配置错误和调试问题提供了实用的解决方案,帮助开发者高效构建企业级桌面应用。 阅读详情

相关推荐

UE5摄像机抖动全攻略:从Perlin噪点到Sequence实战(附参数调优技巧)

本文深入解析UE5摄像机抖动技术,从Perlin噪点算法到CameraShakeBase蓝图应用,再到Sequence高级控制,提供全面的参数调优技巧。涵盖战斗、爆炸等场景的预设参数,帮助开发者实现专业级抖动效果,提升游戏沉浸感。

weixin_30300225的博客 97

synchronized,CountDownLatch理解

1.不管synchronized是用来修饰方法,还是修饰代码块,其本质都是锁定某一个对象。修饰方法时,锁上的是调用这个方法的对象,即this;修饰代码块时,锁上的是括号里的那个对象 在上面的代码中,很明显就是锁定的MyTask对象本身。但是由于在每一个线程中,MyTask对象都是独立的,这就导致实际上每个线程都对自己的MyTask进行锁定,而并不会干涉其它线程的MyTask对象。换言之,上锁

UnionIBM的博客 1981

地心地固坐标系与北天东坐标系的转换

经过这一步旋转,x3轴和y3轴就处在过O3点的经度线所在的平面了,而且z3轴指向了东。将图3的坐标系旋转成图2的样子。这里需要多次旋转,每次以某个轴为对称轴进行旋转,对应的坐标变换参考。的原点在地心,Z轴指向北极点,X轴指向本初子午线与赤道的交点,Y轴指向符合右手定则,如下图所示。下面实现地心地固坐标系到北天东坐标系的转换,问题描述为:设一点。以y1轴为对称轴,顺时针旋转90°,得到图4的样子。,X轴指向北,Y轴指向天,Z轴指向东,如下图所示。因此,北天东坐标下的坐标为。点在图3坐标系下的坐标。

csdnqixiaoxin的博客 3556

并发闭锁之CountDownLatch和FutureTask

闭锁:一种同步工具类,可以用来确保某些活动指导其他活动都完成后才执行。 CountDownLatch:一种闭锁的实现,可以使一个或多个线程等待一组事件发生。 FutureTask:一种闭锁的实现 ...

qq_36955645的博客 3130

携程登录风控逆向踩坑实录:从滑块到点选验证码,我是如何一步步拿到phantom-token的

本文详细解析了携程登录风控系统的逆向过程,从滑块验证码到点选验证码的破解,再到设备指纹生成和加密协议逆向,最终成功获取phantom-token。文章提供了关键代码示例和实战技巧,帮助开发者理解并绕过复杂的风控机制。

weixin_28049429的博客 973

微信小程序如何集成EasyRTC实现零插件音视频通话?5步搞定完整接入流程

本文详细介绍了如何在微信小程序中集成EasyRTC SDK,实现零插件的实时音视频通话功能。通过5个关键步骤,包括环境配置、SDK初始化、核心功能实现、性能优化和问题排查,帮助开发者快速完成WebRTC技术在小程序中的落地应用,解决微信小程序原生不支持实时音视频通信的技术难题。

weixin_28340315的博客 144

java并发:FutureTask 和 CountDowmLatch 的使用

package com; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; /** *

qq_24551315的博客 594

AWS RDS 介绍 三)创建 RDS 实例

AWS RDS 介绍 共分为 7 个部分, 其中 第 3部分重点介绍,如何创建一个RDS 实例。 三) AWS RDS 试用MySQL http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_GettingStarted.CreatingConnecting.MySQL.

XuYongshi02的专栏 7646

信号量(Semaphore)与线程计数器(CountDownLatch)

本文介绍了共享锁中的信号量(Semaphore)和线程计数器(CountDownLatch),从各自的构造方法与常用方法出发,介绍了各自的用法及应用场景,并分别用代码实现示例进一步介绍说明他们的用法

X_H学Java的博客 2599

Gmsh+OCC对应版本库编译

输入 GMSH_DLL_EXPORT值C:\LIB\OCCT-7_8_0-i;9、如果只是生成库文件编译gmesh工程即可生成文件在C:\LIB\Gmsh\gmsh-4.13.1-Windows64-B\Debug 下gmsh.dll、gmsh.lib、gmsh.h、gmshc.h文件;3、CMAK编译Gmsh对应OCC版本的,CMAK选择源文件路径C:\LIB\Gmsh\gmsh-4.13.1-source,生成构建文件路径C:\LIB\Gmsh\gmsh-4.13.1-Windows64-B。

u013401364的博客 412

【四足机器人项目实战】四足机器人腿部机械结构设计

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录系列文章目录前言 前言 认知有限,望大家多多包涵,有什么问题也希望能够与大家多交流,共同成长! 本文先对四足机器人–腿部机械结构设计做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章 提示:以下是本篇文章正文内容 为了减轻腿部惯量,使用有限元分析着重进行轻量化设计,小腿采用工字梁方案,大腿采用内部镂方案,并使用1.5 mm的AL 6061硬质材料,轻量化的腿部设了腿部运动时摆动

qq_35635374的博客 7539

Java并发编程 闭锁:FutureTask、CountDownLatch、Semaphore常见使用方法

一、什么是闭锁 闭锁是一种同步工具,可以延迟线程的进度直到终止状态。可以把它理解为一扇门,当闭锁到达结束状态之前,这扇门一直是关闭的,没有任何线程可以通过。当闭锁到达结束状态时,这扇门会打开并允许所有线程通过,并且闭锁打开后不可再改变状态。 闭锁可以确保某些任务直到其他任务完成后才继续往下执行。 这篇博客只讲述这些闭锁常见用法,如果想深入了解其中原理的话请参考其它博客。 二、FutureT...

APlus 2616

华为OD面试手撕真题 - 最大数

华为OD面试手撕真题 最大的数 提供Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解

qq_45776114的博客 343

Java 中的Synchronizer

1. 闭锁(Latch)     闭锁是一种Synchronizer,它可以延迟线程的进度直到线程达到终止状态。一个闭锁工作起来就像一道大门:直到闭锁达到终点状态之前,门一直是关闭的,没有线程能通过,在终点状态到来的时候,门开了,允许所有线程都通过。一旦闭锁到达了终点状态,它就不能够再改变状态了,所以它永远保持敞开状态。闭锁可以用来确保特定活动,直到其他的活动完成之后才发生。     Coun

wangkr的专栏 1905

数学建模模型总结

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

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

同步器Synchronizer

闭锁 FutureTask 信号量 关卡

ShiXueTanLang的博客 2235

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

多线程实战运用【线程池结合CountDownLatch(信号量)、FutureTask获取反数据】

主方法入参threadSize线程池数量。 通过FutureTask 来获取线程执行返回的数据。 public static Map<String, String> demo(int threadSize) { Map<String, String> map = new HashMap<>(); CountDownLa...

cyang的博客 1305

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Java多线程实战:FutureTask与CountDownLatch的完美结合

前提概要 在知乎上看到一道Java多线程的笔试题,心想我多线程只会Thread和Runable,在写WebFluxTest用过一次CountDownLatch,除此之外还没怎么去看cocurrent包下的类,所以就想试试。 题目 知乎传送门:某大型电商Java面试题:一主多从多线程协作 客户请求下单服务(OrderService),服务端会验证用户的身份(RemotePassportS...

青云桑的小窝 9745

FutureTask与CountDownLatch的结合使用

现在又这样一个场景,用户下单服务(OrderServe)再下但之前需要调用用户服务验证用户信息,要调用账户服务验证账户,要调用贷款服务验证贷款信息,等等,这几个服务异步调用太慢,导致改下单服务非常慢,这几个验证之间有没有任何关联,最终结果所有验证结果都通过就算成功,有也给不通过就失败,所有这几个验证可以同步进行 怎么来优化。 这里我结合FutureTask与CountDownLatch使用 3个服务类,这里只贴一个类 其他一样 /** * 模拟征信验证 */ public class RemoteB

weixin_43606738的博客 1057

Synchronized详解

Synchronized详解 1、同步器的意义 多线程编程中,有可能会出现多个线程同时访问同一个共享、可变资源的情况,这个资源我们称之其为临界资源;这种资源可能是:对象、变量、文件等。 共享:资源可以由多个线程同时访问 可变:资源可以在其生命周期内被修改 Java 中,提供了两种方式来实现同步互斥访问:synchronized 和 Lock 同步器的本质就是加锁,加锁目的:序列化访问临界资源,即同一时刻只能有一个线程访问临界资源(同步互斥访问) 当多个线程执行一个方法时,该方法内部的局部变量并不是临

一名蒟蒻的博客 382

Java笔记-对CountDownLatch的理解(对比Qt中的QSemaphore)含实例

首先在CountDownLatch,这个东西基本上和信号量是一样的,这个CountDownLatch要设置一个初值,这个值一般是个正值,可以对这个CountDownLatch进行countDown()也就是减1,当减少为0时,await()函数就会从阻塞变成就绪态。 下面是Java代码,举个例子,此例子来源于博客园大神,3个工人干活,3个都干完后,老版才开始检查工作,运行截图如下: 源码如下: Boss.java package cn.it1995; import java.util..

IT1995的博客 1107

Java并发编程第9讲——CountDownLatch、CyclicBarrier和Semaphore(万字详解)

在JDK的并发包(JUC)里提供了几个非常有用的并发工具类。CountDownLatch、CyclicBarrier和Samaphore工具类提供了一种并发流程控制的手段,这同样也是面试和工作中的一个重要知识点,本文将从它们的定义、常用方法、代码示例及核心源码的分析等几个要点详细介绍一下。

让~学习~成为一种习惯(橡 皮 人の技术博客) 2877

【并发编程】AQSSemaphore(信号量) CountDownLatch (倒计时器) CyclicBarrier(循环栅栏) ThreadLocal

它的原理是通过一个计数器来实现的,计数器的初始值可以设置为任意正整数,每当一个线程完成了一定的任务,就将计数器的值减1,当计数器的值达到零时,表示所有线程都已经完成任务,等待在CountDownLatch上的线程将被唤醒。调用wait()方法的原因通常是,调用线程希望某个特殊的状态(或变量)被设置之后再继续执行。它的原理是通过一个计数器和一个屏障点来实现的,计数器的初始值可以设置为任意正整数,当线程到达屏障点时,将计数器的值减1,当计数器的值达到零时,所有等待在CyclicBarrier上的线程将被唤醒。

2301_79456272的博客 1088

CountDownLatch 闭锁、FutureTask、Semaphore信号量、Barrier栅栏

  同步工具类可以是任何一个对象。阻塞队列可以作为同步工具类,其他类型的同步工具类还包括信号量(Semaphore)、栅栏(Barrier)、以及闭锁(Latch)。   所有的同步工具类都包含一些特定的结构化属性:它们封装了一些状态,这些状态将决定执行同步工具类的线程是继续执行还是等待,此外还提供了一些方法对状态进行操作,以及另一些方法用于高效地等待同步工具类进入到预期状态。 1....

weixin_30872499的博客 264

Semaphore和CountDownLatch详解

而调用await()方法时,当前线程就会判断state属性是否为0,如果为0,则继续往下执行,如果不为0,则使当前线程进入等待状态,直到某个线程将state属性置为0,其就会唤醒在 await()方法中等待的线程。Semaphore,俗称信号量,他是操作系统中PV操作原语在Java层面的实现,它也是基于AQS实现的。当幻想之后下一个线程就可以被唤醒执行后面的逻辑,假设被唤醒的线程可以获取到资源 ,它又会重新进入doAcquireSharedInterruptibly的for循环执行上面的获取资源的流程。

qq_43456605的博客 1522

JDK5新特性--java.util.concurrent CountDownLatch(5)

从 名字可以看出,CountDownLatch 是一个倒数计数的锁,当倒数到0时触发事件,也就是开锁,其他人就可以进入了。在一些应用场合中,需要等待某个条件达到要求后才能做后面的事情;同时当线程都完成后也会触发事件,以便进行后面的操作。 CountDownLatch最重要的方法是countDown()和await(),前者主要是倒数一次,后者是等待倒数到0,如果没有到达0,就只有阻塞等待了。 一...

南村土人 231

多线下,CountDownLatch,Future的使用

在处理业务的时候,往往需要发起多个线程去查询,处理,然后等待所有线程执行完,再进行业务合并处理。 1,CountDownLatch的使用 CountDownLatch更像是一个计数器,可以设置线程数,进行递减。countDownLatch.countDown();线程处理完以后减少,countDownLatch.await();等待所有的线程处理完。举例: public static voi

dandanlf的博客 3751
上一篇: 阻塞队列 生产者-消费者模式 窃取工作模式(java并发编程实践读书笔记二)
下一篇: javaEE 使用ServletContext实现服务器端简单定时更新缓存
wbean
博客等级 码龄17年 19粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值