【并发编程】同步辅助类

在jdk1.5之后,引入了几个并发编程同步辅助类,它们都在java.util.concurrent包下,分别是CountDownLatch、CyclicBarrier、Semaphore。

CountDownLatch

这个工具类可以理解为计数器,它允许一个或多个线程一直等待,直到其他线程执行完后再执行。

例如,有任务A和B,任务A需要并发执行以提高效率,任务B则需要等待任务A完成之后才能执行,这时候就可以用该工具类。

CountDownLatch只有一个构造函数:

即,传入一个初始值count来确定有多少个任务(入参不得小于0,否则会抛出异常),该值存于AbstractQueuedSynchronizer类里(AQS,在《【并发编程】一文详解Java中的各种锁》中有介绍),声明为volatile,即对内存可见,保证多线程下该值同时只能被一个线程修改(关于volatile参考《【并发编程】揭开volatile的神秘面纱》),每当执行完一个任务,count减1,直到为0,所有任务执行完毕。

重要方法

1:await():调用此方法线程会被阻塞,直到count为0。
2:await(long timeout, TimeUnit unit):同await(),可以设置最大等待时间,如超过最大等待时间则不再等待。
3:countDown():count减1,直至为0。

举个简单的例子,一个班级里有10个学生,在一场考试中,每有一个学生交卷,计数器就减1,老师想要统计学生的平均成绩就必须要等待他们全部交完试卷,即计数器为0。

代码如下:

打印结果:

等待所有学生交卷
学生1正在考试……
学生5正在考试……
学生9正在考试……
学生1已交卷
学生5已交卷
学生0正在考试……
学生4正在考试……
学生4已交卷
学生9已交卷
学生0已交卷
学生8正在考试……
学生3正在考试……
学生7正在考试……
学生2正在考试……
学生6正在考试……
学生7已交卷
学生2已交卷
学生3已交卷
学生6已交卷
学生8已交卷
全部学生已经交卷,正在计算平均分

CyclicBarrier

CyclicBarrier是一个可循环使用(Cyclic)的屏障(Barrier)。它能做的事情是让一组线程到达一个屏障(同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会放行,所有被屏障拦截的线程继续执行。常用于多线程分组计算。

CyclicBarrier有两个构造函数:

CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,线程使用await()方法通知CyclicBarrier该线程已经到达了屏障,并使计数器减1,然后当前线程被阻塞直到计数器为0。

CyclicBarrier的另一个构造函数CyclicBarrier(int parties, Runnable barrierAction),当拦截的线程数等于parties(即count等于0)时,先执行barrierAction,然后再放行被拦截的线程,方便处理更复杂的业务场景(如多线程分组计算先汇总后处理)。

重要方法

1、await():在CyclicBarrier上进行阻塞等待,并使count减1。
2、await(long timeout, TimeUnit unit):在CyclicBarrier上进行限时的阻塞等待,并使count减1,当时间到达限定时间后,线程继续执行。
3、getParties():获取CyclicBarrier通过屏障的线程数量,也称为方数。
4、getNumberWaiting():获取正在CyclicBarrier上等待的线程数量。

这就跟火车站载人的黑车司机一样,并不是上去一个乘客就开车,而是为了使利益最大化,等到车上乘客满了才会发一次车。

代码如下:

打印结果:

乘客+1,等待满员
乘客+1,等待满员
乘客+1,等待满员
乘客+1,等待满员
乘客+1,等待满员
乘客已经满5人,准备上车
乘客已上车
乘客已上车
乘客已上车
乘客已上车
乘客已上车

也就是说,当乘客满五个之后,才会执行屏障线程方法和后面的乘客上车方法,否则一直等待。

Semaphore

Semaphore类是一个计数信号量。计数信号量会初始化指定数量的 “许可” 。每调用一次 acquire(),一个许可就会被调用线程取走;每调用一次 release(),一个许可就会被返还给信号量。因此,在没有任何 release() 调用时,最多有 N 个线程能够通过 acquire() 方法,N 是该信号量初始化时指定的许可数量。

Semaphore有两个构造函数:

permits即为许可数量,默认构造函数为创建拥有permits个许可的计数信号量并设置为非公平信号量。

如果传入fair为true,则创建拥有permits个许可的计数信号量并设置为公平信号量。

公平信号量和非公平信号量的区别在于,当一个许可被释放后,等待的线程是随机获取许可还是按照先后顺序获取(此处可参考《【并发编程】一文详解Java中的各种锁》中公平锁与非公平锁)。

重要方法

1、acquire():从信号量获取1个许可,信号量内部计数器减1,如果没有许可,线程将一直阻塞。
2、acquire(int permits):从信号量获取permits个许可,在提供这些许可前,线程一直阻塞。
3、release():释放1个许可,将其返回给信号量,信号量内部计数器加1。
4、release(int permits):释放permits个许可。
5、availablePermits():当前可用的许可数。
6、tryAcquire():尝试地获得1个许可,如果获取不到则返回false。
7、tryAcquire(long timeout, TimeUnit unit):在指定的时间内尝试地获得1个许可,如果获取不到则返回false。
8、tryAcquire(int permits):尝试地获得permits个许可,如果获取不到则返回false。
9、tryAcquire(int permits, long timeout, TimeUnit unit):在指定的时间内尝试地获得permits个许可,如果获取不到则返回false。

举个例子,一个停车场有五个车位,同时来了十辆车需要停车。

代码如下:

打印结果:

来了一辆车0
有车位,0停车入位
来了一辆车2
有车位,2停车入位
来了一辆车3
来了一辆车7
有车位,7停车入位
有车位,3停车入位
来了一辆车4
有车位,4停车入位
来了一辆车1
来了一辆车6
来了一辆车8
来了一辆车9
来了一辆车5
2离开车位
7离开车位
3离开车位
有车位,6停车入位
有车位,1停车入位
有车位,8停车入位
0离开车位
4离开车位
有车位,9停车入位
有车位,5停车入位
1离开车位
9离开车位
5离开车位
8离开车位
6离开车位

总结

在java.util.concurrent包下,还有很多并发编程的工具类,如atomic原子类,Lock类,ConcurrentHashMap,还有《【并发编程】Java线程池详解》中介绍的线程池等,非常值得学习。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容