闭锁,信号量,栅栏

article/2025/10/4 10:43:04

1.   闭锁(countDownLatch)

1.1.     作用:

相当于一扇门,在闭锁到达结束状态之前,这扇门是关着的,所以的线程都不允许通过,当闭锁到达结束状态,这扇门打开并允许所有的线程通过。在闭锁达到结束状态后,将不会再改变状态,这扇门永远处于打开状态。

1.2.     闭锁使用场景

1) 确保某个计算在其所有资源都被初始化之后才继续执行;

2) 确保某个服务在其所有所依赖的服务都已经启动后在启动;

3) 等待某个操作的所有参与者都就绪再继续执行(例如王者荣耀匹配成功后需等待所有玩家确认后才能进行选英雄)。

1.3.     闭锁的简单使用

CountDownLatch是一种灵活的闭锁实现,上述场景都可以均可使用。该类的简单用法如下:

public class SysUtil {final CountDownLatch startGate;final CountDownLatch endGate;public static void main(String[] args) throws InterruptedException {int num = 20;SysUtil sysUtil = new SysUtil(1, num);for (int i = 0; i < num; i++) {Thread thread = new Thread(sysUtil.new Worker());thread.start();}long time = System.currentTimeMillis();System.out.println("准备好所需的资源");// doPreparedResource()// open the door
sysUtil.startGate.countDown();try {// 等待所有线程执行完成
sysUtil.endGate.await();} catch (InterruptedException e) {e.printStackTrace();}long endTime = System.currentTimeMillis();System.out.println(endTime - time);}public SysUtil(int start, int end) {startGate = new CountDownLatch(start);endGate = new CountDownLatch(end);}class Worker implements Runnable{private final CountDownLatch startSignal;private final CountDownLatch doSignal;public Worker() {this.startSignal = startGate;this.doSignal = endGate;}@Overridepublic void run() {try {startSignal.await();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() +": i through the startGate");doSignal.countDown();}}}
View Code

上面代码使用了两个闭锁,分别表示“起始门”和“结束门”,起始门初始值设置为1,结束门设置为工作线程数量。在资源未完成加载之前(doPreparedResource()),所有线程被拒之起始门外,加载完资源后,大门打开,线程进入办公楼开始干活,等到下班时间了,办公大楼就可以打开结束门放线程回家。

 

2.   FutureTask

2.1.     简介

FutureTask实现了Future语义,表示一直抽象的可生成结果的计算。FutureTask表示的计算是通过Callable来实现的。计算结果通过get()方法获得,如果任务已经完成,那么get方法会立即返回结果,否则get方法将阻塞直到任务进入完成状态(包括正常结束、由于取消而结束及由于异常而结束),然后返回结果或抛出异常。

public class FutureTask<V> implements RunnableFuture<V>

public interface RunnableFuture<V> extends Runnable, Future<V>

Runable接口我们熟悉只有一个run()方法

Future接口方法如下:

2.2.     FutureTask的简单使用

public class FutureTaskTest {@Testpublic void test() throws InterruptedException, ExecutionException {FutureTask<Integer> futureTask = new FutureTask<>(new Task());Thread thread = new Thread(futureTask);long startTime = System.currentTimeMillis();thread.start();System.out.println("result: " + futureTask.get());long endTime = System.currentTimeMillis();System.out.println("花费时间:" + (endTime - startTime));}class Task implements Callable<Integer>{@Overridepublic Integer call() throws Exception {System.out.println("--------线程执行中------------");int sum = 0;for (int i = 0; i < 100; i++) {Thread.sleep(10);sum += i;}return sum;}}}
View Code

3.   信号量(Semaphore)

3.1.     简介

计数信号量用来控制同时访问某个特定资源的操作数量,或者同时执行某个指定操作的数量。另外信号量还可以用来实现某种资源池,或对容器施加边界。

Semaphore中管理着一组虚拟许可(permit),许可的初始数量可通过构造函数来指定,在执行操作之前首先获得(acquire)许可,在使用后释放许可。如果没有许可,那么acquire将阻塞直到有permit(或者直到被中断或操作超时)。Release方法将返回一个许可给信号量。

3.2.     简单使用

/** 利用信号量对set设置边界*/public class SemephoreTest<T> {private final Set<T> set;private final Semaphore semaphore;public SemephoreTest(int boundNum) {this.set = Collections.synchronizedSet(new HashSet<>());// 创建一定数量的许可this.semaphore = new Semaphore(boundNum);}public boolean add(T o) {boolean wadAdd = false;try {// 请求许可
semaphore.acquire();wadAdd = set.add(o);return wadAdd;} catch (InterruptedException e) {e.printStackTrace();}finally {// 元素添加失败,释放许可if (!wadAdd) {semaphore.release();}}return wadAdd;}public boolean remove(T o) {boolean wasRemoved = set.remove(o);if (wasRemoved) {semaphore.release();}return wasRemoved;}}
View Code

 

4.   栅栏(barrier)

4.1.     简介

栅栏类似于闭锁,它能阻塞一组线程直到某个事件发生。栅栏和闭锁的区别在于,所有线程必须都到达栅栏位置了,才能继续执行。闭锁用于等待事件,而栅栏用于等待其他线程。

CyclicBarrier可以使一定的数量的参与方反复地在栅栏处汇集,在并行迭代算法中非常有用。但线程到达栅栏处时将调用栅栏的await方法,该方法会阻塞当前线程直到所有的线程都到达了栅栏处。如果所有的线程都到达了栅栏处,栅栏将会打开,此时所有的线程都会被释放,而栅栏将被重置以便下次使用(闭锁不可被重置)。如果await调用超时或者阻塞的线程被中断,所有的await调用都终止并抛出BrokenBarrierException。如果成功通过栅栏,await将为每个线程返回唯一的到达索引号。

4.2.     简单使用

public class BarrierTest {private final CyclicBarrier cyclicBarrier;private Worker[] workers;public BarrierTest() {int count = Runtime.getRuntime().availableProcessors() * 2;count = 10;cyclicBarrier = new CyclicBarrier(count, new Runnable() {@Overridepublic void run() {System.out.println("open the barrier");}});this.workers = new Worker[count];for (int i = 0; i < workers.length; i++) {workers[i] = new Worker();}}class Worker implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + ":我到了,等人齐");try {cyclicBarrier.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "冲啊");}}public void start() {for (int i = 0; i < workers.length; i++) {new Thread(workers[i]).start();}}// 不可使用Junit进行多线程的测试,Junit中是将当前 test作为参数,放入到 Junit TestRunner中的main函数// 作为一个子线程运行,当测试线程运行成功,将把jvm停止。具体看下面代码/*public static void main(String args[]) {TestRunner aTestRunner = new TestRunner();try {TestResult r = aTestRunner.start(args);if (!r.wasSuccessful())System.exit(FAILURE_EXIT);System.exit(SUCCESS_EXIT);} catch (Exception e) {System.err.println(e.getMessage());System.exit(EXCEPTION_EXIT);}}*/@Testpublic void test() {new BarrierTest().start();}public static void main(String[] args) {new BarrierTest().start();}}
View Code

5.   Exchanger(两方栅栏)

5.1.     简介

Exchanger类可用于两个线程之间交换信息,是一种两方栅栏。可简单地将Exchanger对象理解为一个包含两个格子的容器,通过exchanger方法可以向两个格子中填充信息。当两个格子中的均被填充时,该对象会自动将两个格子的信息交换,然后返回给线程,从而实现两个线程的信息交换。

另外需要注意的是,Exchanger类仅可用作两个线程的信息交换,当超过两个线程调用同一个exchanger对象时,得到的结果是随机的,未得到配对的线程,则会被阻塞,永久等待,直到与之配对的线程到达位置,exchanger对象仅关心其包含的两个“格子”是否已被填充数据,当两个格子都填充数据完成时,该对象就认为线程之间已经配对成功,然后开始执行数据交换操作。

5.2.     简单使用

public class ExchangerTest {public static void main(String[] args) {Exchanger<String> barrier = new Exchanger<>();Comsumer comsumer = new ExchangerTest(). new Comsumer(barrier);Producer prodecer = new ExchangerTest(). new Producer(barrier);Thread thread1 = new Thread(comsumer);Thread thread2 = new Thread(prodecer);thread1.start();thread2.start();}class Comsumer implements Runnable{private Exchanger<String> changer;public Comsumer(Exchanger<String> exchanger) {this.changer = exchanger;}@Overridepublic void run() {String changes = null;try {changes = changer.exchange("money");} catch (InterruptedException e) {// TODO Auto-generated catch block
e.printStackTrace();}System.out.println("Consumer recieve:" + changes);}}class Producer implements Runnable{private Exchanger<String> changer;public Producer(Exchanger<String> exchanger) {this.changer = exchanger;}@Overridepublic void run() {String changes = null;try {changes = changer.exchange("products");} catch (InterruptedException e) {// TODO Auto-generated catch block
e.printStackTrace();}System.out.println("Producer recieve:" + changes);}}}
View Code

 

转载于:https://www.cnblogs.com/X-huang/p/11218358.html


http://chatgpt.dhexx.cn/article/NAaVDFb4.shtml

相关文章

visio 2010激活教程

一、下载office2010toolkit.zip 若下载链接失效&#xff0c;手动搜索office2010toolkit http://ys-c.ys168.com/605279628/o4W138W45JIPI5SiuWf5/office2010toolkit.zip二、激活 激活过程中需要关闭office套件

Microsoft Visio Professional 2013 安装步骤

1.打开解压后的文件夹&#xff0c;点击setup.exe安装 2.勾选我接受此协议的条款&#xff0c;继续 3.点击立即安装 4.安装完成&#xff0c;关闭。 5.打开第一步解压的文件夹中破解文件夹&#xff0c;鼠标右键以管理员身份运行 6.点击激活office2013VL 7.激活完成 Microsoft Visi…

激活Visio2013

最近需要用Visio&#xff0c;由于密钥过期了&#xff0c;也不知道怎么重新输密钥&#xff0c;于是网上搜索&#xff0c;终于找到了一个方法。 KMSpico工具&#xff0c;安装完后直接打开点击左边红色按钮就可以了。如图&#xff1a; 最后附上工具链接https://pan.baidu.com/s/1…

机器学习十大算法之-CART分类决策树、回归树和模型树

转载&#xff08;http://blog.163.com/zhoulili1987619126/blog/static/35308201201542731455261/&#xff09; Classification And Regression Tree(CART)是决策树的一种&#xff0c;并且是非常重要的决策树&#xff0c;属于Top Ten Machine Learning Algorithm。顾名思义&…

决策树入门以及树模型的参数选择

决策树及树模型的参数选择 决策树的基本概念 在数据结构中树是一个重要的数据结构&#xff0c;这里树被我们根据分支起到一个决策的作用。什么是决策&#xff1f;通俗的说就是判断或者决定&#xff0c;我们引用周志华的西瓜书中的例子&#xff1a;这是一个好瓜吗&#xff1f;当…

gbdt、xgb、lgb决策树模型

目录 1.决策树1.1 CART分类树1.2 CART回归树 2.gbdt3.xgboost4.lightgbm5.模型对比6.参考文献 本文主要对决策树、gbdt、xgboost、lightgbm、catboost进行简述和整理&#xff0c;包括模型原理、优劣性等内容 1.决策树 决策树是一种通过对历史数据进行测算&#xff0c;对新数据…

树模型与线性模型的融合模型(Python实现)

目录 一、树模型与线性模型的融合模型 二、Python sklearn实现GBDTLR融合模型 一、树模型与线性模型的融合模型 树模型GBDT原理&#xff1a;https://blog.csdn.net/woniu201411/article/details/83114226 线性模型LR原理&#xff1a;https://blog.csdn.net/woniu201411/art…

机器学习理论与实战(九)回归树和模型树

前一节的回归是一种全局回归模型,它设定了一个模型,不管是线性还是非线性的模型,然后拟合数据得到参数,现实中会有些数据很复杂,肉眼几乎看不出符合那种模型,因此构建全局的模型就有点不合适。这节介绍的树回归就是为了解决这类问题,它通过构建决策节点把数据数据切分成…

决策树模型

本文代码及数据集来自《Python大数据分析与机器学习商业案例实战》 决策树模型的建树依据主要用到的是基尼系数的概念。基尼系数&#xff08;gini&#xff09;用于计算一个系统中的失序现象&#xff0c;即系统的混乱程度。基尼系数越高&#xff0c;系统的混乱程度就越高&#x…

新版HyperMesh的Assemblies中调出下拉菜单查看Component(装配关系模型树)

新版HyperMesh的Assemblies中调出下拉菜单查看Component&#xff08;装配关系模型树&#xff09; 从Altair更新的2019版本开始&#xff0c;在Model模型树中找不到Assemblies了&#xff0c;这样导致好多用户一直在用14或者17版本&#xff0c;其实这次更新不是把这个功能取消掉了…

Cesium bim模型加载并与模型树关联(分层加载)

很久都没写文章了&#xff0c;最近实在是太忙了&#xff0c;向各位关注我的小伙伴致个歉&#xff01; 最近没事儿写了个模型树和模型关联的功能&#xff0c;处理工具是用的cesiumlab。 说明一下为什么要用cesiumlab&#xff1a; 网上现在有很多的模型转换工具&#xff0c;如…

举例讲清楚模型树和回归树的区别

根据上面图中的一个例子&#xff0c;我们来分析下&#xff0c;假设A、B两点是曲线上的噪声点。 模型树的叶子节点是一个分段线性函数[1]。 回归树的叶子节点是取一个区间的平均(一个常数值)。 上述图中AB区间的均值是一个暗点。 所以&#xff1a; 对于节点A而言&#xff0c;模…

[Ansys Workbench] Mechanical 界面显示模型树窗口和详细信息窗口

根据这个回答才找到的……我之前也没注意&#xff0c;别人问我我才去想的 https://forum.ansys.com/discussion/8740/workbench-tree-outline 一般的方法是在 主页 - 布局 - 管理 里面选择显示哪个视窗 如果就是想显示模型树窗口和详细信息窗口&#xff0c;可以使用快捷键 Ctr…

creo文件如何检入服务器,CREO模型树配置的保存与检索

保存模型树配置 (1)单击 然后单击“保存设置文件”(Save Settings File)。“保存模型树配置”(Save Model Tree Configuration) 对话框打开。 (2)接受默认文件名 tree.cfg 或键入新名称。 (3)单击“保存”(Save)。 手动检索模型树配置 (1)单击 然后单击“打开设置文件”(Open S…

Graphviz绘制模型树2——XGBoost模型的可解释性

从二分类模型中的树重新理解XGBoost算法 一.对绘制的树简单解释1.1类别判断1.2树的最大层级1.3效果较差情况 二.从数据来解释一棵树2.1EXCEL构建第1颗树2.2第1棵树的数据解释2.3效果较差的节点解释 三.N颗树如何预测样本3.1样本22数据3.2样本22落入叶子情况3.3样本22的总结 四.…

决策树(二):回归树和模型树

下面介绍的回归树和另一篇文章介绍的分类树&#xff0c;都属于决策树范畴。分类树的模型是每个非叶子节点都是一个分类特征&#xff0c;按照该分类特征的不同取值&#xff0c;将数据集分为多少个子集&#xff1b;并且分类树模型我们要找的是测试数据集的最终分类结果&#xff0…

模型树——就是回归树的分段常数预测修改为线性回归 对于非线性回归有较好的预测效果...

说完了树回归&#xff0c;再简单的提下模型树&#xff0c;因为树回归每个节点是一些特征和特征值&#xff0c;选取的原则是根据特征方差最小。如果把叶子节点换成分段线性函数&#xff0c;那么就变成了模型树&#xff0c;如&#xff08;图六&#xff09;所示&#xff1a; &…

《机器学习实战》9.3树回归之模型树和项目案例

《机器学习实战》9.3树回归之模型树和项目案例 搜索微信公众号:‘AI-ming3526’或者’计算机视觉这件小事’ 获取更多人工智能、机器学习干货 csdn&#xff1a;https://blog.csdn.net/baidu_31657889/ github&#xff1a;https://github.com/aimi-cn/AILearners 本文出现的所有…

模型树–M5

模型树–M5 模型树推广了回归树的概念&#xff0c;它与回归树的2个重要不同在于&#xff1a; 叶节点上不是常量&#xff0c;而是一个线性函数模型。分割空间的标准不是降低平方误差&#xff0c;而是降低样本标准差。 相比于回归树&#xff0c;模型树的优点在于&#xff1a;回…

机器学习——模型树

和回归树&#xff08;在每个叶节点上使用各自的均值做预测&#xff09;不同&#xff0c;模型树算法需要在每个叶节点上都构建出一个线性模型&#xff0c;这就是把叶节点设定为分段线性函数&#xff0c;这个所谓的分段线性&#xff08;piecewise linear&#xff09;是指模型由多…