CyclicBarrier与CountDownLatch区别
阻塞与唤醒方式的区别
CountDownLatch计数方式
CountDownLatch是减计数。调用await()后线程阻塞。调用countDown()方法后计数减一,当计数为零时,调用await()的线程被唤醒。
CountDownLatch应用场景为:
一个或一组线程等待另一组线程完成操作后恢复执行
CountDownLatch例子: 模拟赛跑
开始时一组运动员线程等待begin计数器(初始值为1),当主线程调用begin.countDown()后begin减1,计数器为0,这一组运动员线程同时起跑。主线程等待end计数器(初始值为10)。一个运动员线程到达终点后,调用end.countDown(),end计数器减1。当所有运动员都到达终点后,end计数器为0,主线程恢复执行。
package CountDownLatch;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class RaceSimulation {
public static void main(String args[]){
//比赛开始的倒数锁
CountDownLatch begin=new CountDownLatch(1);
//比赛结束的倒数锁
CountDownLatch end=new CountDownLatch(10);
//十个选手跑步线程
final ExecutorService exec = Executors.newFixedThreadPool(10);
for(int index= 0;index<10;++index){
final int NO=index+1;
Runnable run = new Runnable(){
@Override
public void run() {
try{
//如果计数不为0,则一直等待
//如果当前计数为0,此线程立即执行
begin.await();
Thread.sleep((long)(Math.random()*10000));
System.out.println("No."+NO+" arrived");
}catch(InterruptedException e){
e.printStackTrace();
}finally{
//每个选手到达终点时,end就减1
end.countDown();
}
}
};
exec.submit(run);
}
System.out.println("游戏开始:");
//begin减1,开始游戏
begin.countDown();
//等待end变为0,即所有选手到达终点
try {
end.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("游戏结束");
exec.shutdown();
}
}
CyclicBarrier计数方式
CyclicBarrier是加计数。调用await()后线程阻塞计数器加1,当所有线程都到达屏障被阻塞后,这一组线程才一起恢复执行。
CyclicBarrier的应用场景
一组线程到达一个屏障(即执行CyclicBarrier.await())时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程调用await方法告诉CyclicBarrier我已经到达了屏障,然后当前线程被阻塞。
CyclicBarier的例子
package cyclicBarrier;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CyclicBarrierDemo {
public static void main(String[] args) {
int N=4;
CyclicBarrier cyclicBarrier=new CyclicBarrier(N,new Runnable() {
@Override
public void run() {
System.out.println("线程"+Thread.currentThread().getName()+"正在执行所有线程到达屏障后执行的操作");
}
});
ExecutorService exec=Executors.newFixedThreadPool(4);
for(int i=0;i<N;++i) {
Runnable r=()->{
try {
System.out.println("线程"+Thread.currentThread().getName()+"正在执行线程的操作");
//用睡眠代替线程的操作
Thread.sleep(new Random().nextInt(1000));
System.out.println("线程"+Thread.currentThread().getName()+"到达屏障");
cyclicBarrier.await();
System.out.println("线程"+Thread.currentThread().getName()+"越过屏障,线程执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
};
exec.submit(r);
}
exec.shutdown();
}
}
是否可以重用
CountDownLatch不可以重用
CyclicBarrier可以重用
package cyclicBarrier;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CyclicBarrierDemo {
public static void main(String[] args) {
int N=4;
CyclicBarrier cyclicBarrier=new CyclicBarrier(N,new Runnable() {
@Override
public void run() {
System.out.println("线程"+Thread.currentThread().getName()+"正在执行所有线程到达屏障后执行的操作");
}
});
ExecutorService exec1=Executors.newFixedThreadPool(4);
for(int i=0;i<N;++i) {
Runnable r=()->{
try {
System.out.println("线程"+Thread.currentThread().getName()+"正在执行线程的操作");
//用睡眠代替线程的操作
Thread.sleep(new Random().nextInt(1000));
System.out.println("线程"+Thread.currentThread().getName()+"到达屏障");
cyclicBarrier.await();
System.out.println("线程"+Thread.currentThread().getName()+"越过屏障,线程执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
};
exec1.submit(r);
}
exec1.shutdown();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("CyclicBarrier重用");
ExecutorService exec2=Executors.newFixedThreadPool(4);
for(int i=0;i<N;++i) {
Runnable r=()->{
try {
System.out.println("线程"+Thread.currentThread().getName()+"正在执行线程的操作");
//用睡眠代替线程的操作
Thread.sleep(new Random().nextInt(1000));
System.out.println("线程"+Thread.currentThread().getName()+"到达屏障");
cyclicBarrier.await();
System.out.println("线程"+Thread.currentThread().getName()+"越过屏障,线程执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
};
exec2.submit(r);
}
exec2.shutdown();
}
}
CyclicBarrier与CountDownLatch区别的更多相关文章
- CyclicBarrier和CountDownLatch区别
这两天写多线程时,用到了CyclicBarrier,下意识的认为CyclicBarrier和CountDownLatch作用很像,就翻阅资料查了一下,说一下他们的区别吧 CyclicBarrier和C ...
- JAVA多线程提高十:同步工具CyclicBarrier与CountDownLatch
今天继续学习其它的同步工具:CyclicBarrier与CountDownLatch 一.CyclicBarrier CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公 ...
- JAVA多线程学习十三 - 同步工具CyclicBarrier与CountDownLatch
一.CyclicBarrier CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).在涉及一组固定大小的线程的程序 ...
- CountDownLatch、CyclicBarrier、Semaphore 区别
CountDownLatch.CyclicBarrier.Semaphore 区别: CountDownLatch和CyclicBarrier都能够实现线程之间的等待,只不过它们侧重点不同: Coun ...
- JDK源码分析之concurrent包(四) -- CyclicBarrier与CountDownLatch
上一篇我们主要通过ExecutorCompletionService与FutureTask类的源码,对Future模型体系的原理做了了解,本篇开始解读concurrent包中的工具类的源码.首先来看两 ...
- CyclicBarrier和CountDownLatch的差别
CyclicBarrier和CountDownLatch都用多个线程之间的同步,共同点:同时有N个线程在 CyclicBarrier(CountDownLatch) 等待上等待时,CyclicBarr ...
- Java并发之CyclicBarrier、CountDownLatch、Phaser
在Java多线程编程中,经常会需要我们控制并发流程,等其他线程执行完毕,或者分阶段执行.Java在1.5的juc中引入了CountDownLatch和CyclicBarrier,1.7中又引入了Pha ...
- 《java.util.concurrent 包源码阅读》21 CyclicBarrier和CountDownLatch
CyclicBarrier是一个用于线程同步的辅助类,它允许一组线程等待彼此,直到所有线程都到达集合点,然后执行某个设定的任务. 现实中有个很好的例子来形容:几个人约定了某个地方集中,然后一起出发去旅 ...
- 使用数据库乐观锁解决高并发秒杀问题,以及如何模拟高并发的场景,CyclicBarrier和CountDownLatch类的用法
数据库:mysql 数据库的乐观锁:一般通过数据表加version来实现,相对于悲观锁的话,更能省数据库性能,废话不多说,直接看代码 第一步: 建立数据库表: CREATE TABLE `skill_ ...
随机推荐
- forkjoin及其性能分析,是否比for循环快?
最近看了网上的某公开课,其中有讲到forkjoin框架.在这之前,我丝毫没听说过这个东西,很好奇是什么东东.于是,就顺道研究了一番. 总感觉这个东西,用的地方很少,也有可能是我才疏学浅.好吧,反正问了 ...
- 键盘优雅弹出与ios光标乱飘解决方案
前言 在移动开发中,会遇到这样的情况,比如说有一个输入框在最底部的时候,我们弹起输入框,输入框不会在输入键盘上. 说明白简单点就是,输入框被键盘挡住了.而且在原生中,输入框应该正好在输入键盘上,但是h ...
- SpringSecurity 初始化流程源码
SpringSecurity 初始化流程源码 本篇主要讲解 SpringSecurity初始化流程的源码部分,包括核心的 springSecurityFilterChain 是如何创建的,以及在介绍哪 ...
- java类中元素初始化顺序
结论:对于静态变量.静态初始化块.变量.初始化块.构造器,它们的初始化顺序依次是(静态变量.静态初始化块)>(变量.初始化块)>构造器. public class Test4 { @Tes ...
- BZOJ4559&P3270[JLoi2016]成绩比较
题目描述 \(G\)系共有\(n\)位同学,\(M\)门必修课.这\(N\)位同学的编号为\(0\)到\(N-1\)的整数,其中\(B\)神的编号为\(0\)号.这\(M\)门必修课编号为\(0\)到 ...
- 开发者必须要了解的架构技术趋势:Service Mesh
内容概要 Service Mesh 是干啥的?解决了什么问题? Service Mesh 的特性 Service Mesh 的主流实现有哪些? 1. Service Mesh 是什么? 简单来讲,Se ...
- Uva1014:Remember the Word
Neal is very curious about combinatorial problems, and now here comes a problem about words. Knowing ...
- javaWeb传收参数方式总结
有时候,我真会被传参搞得头晕,这样传要怎么接收,那样传又要怎么接收? get可以json吗?什么是json方式提交?等等问题,已困扰我许久 所以,在此想做个总结,整理一下思绪,不再为传收参烦恼!如有错 ...
- 进击.net 三大框架
spring mybatis NHibernate
- 【阿K学Python系列】一Python基础语法(二)
前言 通过上一章的学习[阿k学Python]一Python入门(一),我们已经初步了解到Python是一种解释型.面向对象.动态数据类型的高级程序设计语言,当然也是一门脚本语言,像前端需要学习的Jav ...