Java学习day099 并发(九)(同步器:信号量、倒计时门栓、障栅、交换器、同步队列)
发布日期:2021-06-29 11:49:43 浏览次数:2 分类:技术文章

本文共 2067 字,大约阅读时间需要 6 分钟。

使用的教材是java核心技术卷1,我将跟着这本书的章节同时配合视频资源来进行学习基础java知识。

day099   并发(九)(同步器:信号量、倒计时门栓、障栅、交换器、同步队列)

java.util.concurrent包包含了几个能帮助人们管理相互合作的线程集的类见表。这些机制具有为线程之间的共用集结点模式(commonrendezvouspatterns)提供的“预置功能”(cannedfunctionality)0如果有一个相互合作的线程集满足这些行为模式之一,那么应该直接重用合适的库类而不要试图提供手工的锁与条件的集合。


1.信号量

概念上讲,一个信号量管理许多的许可证(permit)。为了通过信号量,线程通过调用acquire请求许可。其实没有实际的许可对象,信号量仅维护一个计数。许可的数目是固定的,由此限制了通过的线程数量。其他线程可以通过调用release释放许可。而且,许可不是二必须由获取它的线程释放。事实上,任何线程都可以释放任意数目的许可,这可能会增加许可数目以至于超出初始数目。

信号量在1968年由EdsgerDijkstra发明,作为同步原语(synchronization primitive)。Dijkstra指出信号量可以被有效地实现,并且有足够的能力解决许多常见的线程同步问题。在几乎任何一本操作系统教科书中,都能看到使用信号量实现的有界队列。

当然,应用程序员不必自己实现有界队列。通常,信号量不必直接映射到通用应用场景。


2.倒计时门栓

一个倒计时门栓(CountDownLatch)让一个线程集等待直到计数变为0。倒计时门栓是一次性的。一旦计数为0,就不能再重用了。一个有用的特例是计数值为1的门栓。实现一个只能通过一次的门。线程在门外等候直到另一个线程将计数器值置为0。

举例来讲,假定一个线程集需要一些初始的数据来完成工作。工作器线程被启动并在门外等候。另一个线程准备数据。当数据准备好的时候,调用cmmtDown,所有工作器线程就可以继续运行了。

然后,可以使用第二个门栓检査什么时候所有工作器线程完成工作。用线程数初始化门栓。每个工作器线程在结束前将门栓计数减1。另一个获取工作结果的线程在门外等待,一旦所有工作器线程终止该线程继续运行。


3.障栅

CyclicBarrier类实现了一个集结点(rendezvous)称为障栅(barrier)。考虑大量线程运行在一次计算的不同部分的情形。当所有部分都准备好时,需要把结果组合在一起。当一个线程完成了它的那部分任务后,我们让它运行到障栅处。一旦所有的线程都到达了这个障栅,障栅就撤销,线程就可以继续运行。

下面是其细节。首先,构造一个障栅,并给出参与的线程数:

CyclicBarrier barrier = new CydicBarrier(nthreads);

每一个线程做一些工作,完成后在障栅上调用 await :

public void run(){    doWork();    bamer.await();    ...}

await方法有一个可选的超时参数:

barrier.await(100, TineUnit.MILLISECONDS);

如果任何一个在障栅上等待的线程离开了障栅,那么障栅就被破坏了(线程可能离开是因为它调用await时设置了超时,或者因为它被中断了)。在这种情况下,所有其他线程的await方法抛出BrokenBarrierException异常。那些已经在等待的线程立即终止await的调用。

可以提供一个可选的障栅动作(barrieraction),当所有线程到达障栅的时候就会执行这一动作。

Runnable barrierAction = . ..;CyclicBarrier barrier = new Cyc1icBarrier(nthreads, barrierAction);

该动作可以收集那些单个线程的运行结果。障栅被称为是循环的(cyclic),因为可以在所有等待线程被释放后被重用。在这一点上,有别于CountDownLatch,CountDownLatch只能被使用一次。

Phaser类增加了更大的灵活性,允许改变不同阶段中参与线程的个数。


4.交换器

当两个线程在同一个数据缓冲区的两个实例上工作的时候,就可以使用交换器(Exchanger)。典型的情况是,一个线程向缓冲区填人数据,另一个线程消耗这些数据。当它们都完成以后,相互交换缓冲区。


5.同步队列

同步队列是一种将生产者与消费者线程配对的机制。当一个线程调用SynchronousQueue的put方法时,它会阻塞直到另一个线程调用take方法为止,反之亦然。与Exchanger的情况不同,数据仅仅沿一个方向传递,从生产者到消费者。

即使SynchronousQueue类实现了BlockingQueue接口,概念上讲,它依然不是一个队列。它没有包含任何元素,它的size方法总是返回0。


 

转载地址:https://blog.csdn.net/Zzehao11/article/details/105845555 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Java学习day100 并发(十)(线程与Swing:运行耗时的任务、使用Swing工作线程、单一线程规则)
下一篇:Java学习day098 并发(八)(执行器:线程池、预定执行、控制任务组、Fork-Join框架、可完成Future)

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年04月27日 19时09分41秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

垃圾分类背后的数据和真相 2019-04-29
PID算法搞不懂?看这篇文章就够了。 2019-04-29
这位电子工程师,你不能错过。 2019-04-29
十八般武艺教你如何解决问题 2019-04-29
「权威发布」2019年大学生电子设计竞赛,仪器设备和主要元器件清单 2019-04-29
「重磅猜题之第二篇」2019年大学生电子设计竞赛 2019-04-29
知乎:硬件和软件哪个吃香? 2019-04-29
中国深圳,600架无人机的盛典! 2019-04-29
干货分享 JVM 之第 3 篇 —— Java 内存结构相关 2019-04-29
干货分享 JVM 之第 4 篇 —— 掌握 Jmeter 压力测试工具,熟悉 Jconsole.exe 工具 2019-04-29
干货分享 JVM 之第 5 篇 —— 类加载器 2019-04-29
干货分享 JVM 之第 6 篇 —— SpringBoot2.0 框架性能调优 2019-04-29
基于 Hystrix 高并发服务限流第 1 篇 —— 必须了解的相关概念 2019-04-29
基于 Hystrix 高并发服务限流第 2 篇 —— 服务隔离(线程池隔离、信号量隔离) 2019-04-29
基于 Hystrix 高并发服务限流第 3 篇 —— 服务熔断、服务降级 2019-04-29
基于 Hystrix 高并发服务限流第 4 篇 —— 基于 Feign 实现服务熔断降级处理 2019-04-29
基于 Hystrix 高并发服务限流第 5 篇 —— Hystrix 监控 2019-04-29
Eureka 如何快速的、优雅的停止某个微服务 2019-04-29
Eureka 实现安全认证 2019-04-29
基于 Hystrix 高并发服务限流第 6 篇 —— 服务限流,基于 RateLimiter 实现 2019-04-29