java多线程并发控制countDownLatch和cyclicBarrier的使用
java主线程等待所有子线程执行完毕在执行,这个需求其实我们在工作中经常会用到,比如用户下单一个产品,后台会做一系列的处理,为了提高效率,每个处理都可以用一个线程来执行,所有处理完成了之后才会返回给用户下单成功。
我们通过以下的几种方法来解决:
一、使用Thread的join()等待所有的子线程执行完毕,主线程在执行,thread.join()把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程。比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B。
/**
*
* 处理一个业务逻辑的场景:当一组线程都执行完之后,在执行别的线程(后者要使用前者返回的结果)
* @author Administrator
*
*/
public class ThreadDemo { public static void main(String[] args) throws InterruptedException {
Vector<Thread> vectors=new Vector<Thread>();
//启用5个线程
for(int i=1;i<=5;i++){
Thread childrenThread=new Thread(new Runnable(){
public void run(){
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("子线程执行!"); }
});
vectors.add(childrenThread);
childrenThread.start();
}
//主线程
for(Thread thread : vectors){
thread.join(); //使用join来保证childrenThread的5个线程都执行完后,才执行主线程
}
System.out.println("主线程执行!"); } }
二、下面结合这个问题我介绍一些并发包里非常有用的并发工具类,等待多线程完成的CountDownLatch
/**
*
* 处理一个业务逻辑的场景:当一组线程都执行完之后,在执行别的线程(后者要使用前者返回的结果)
* @author Administrator
*
*/
public class ThreadDemo2 { public static void main(String[] args) throws InterruptedException {
final CountDownLatch latch= new CountDownLatch(5);//使用java并发库concurrent
//启用5个线程
for(int i=1;i<=5;i++){
new Thread(new Runnable(){
public void run(){
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("子线程执行!");
latch.countDown();//让latch中的数值减一 }
}).start(); }
//主线程
latch.await();//阻塞当前线程直到latch中数值为零才执行
System.out.println("主线程执行!"); } }
注意:在这里说明一点,countDownLatch不可能重新初始化或者修改CountDownLatch对象内部计数器的值,一个线程调用countdown方法happen-before另外一个线程调用await方法
三、同步屏障CyclicBarrier
/**
*
* 处理一个业务逻辑的场景:当一组线程都执行完之后,在执行别的线程(后者要使用前者返回的结果)
* @author Administrator
*
*/
public class ThreadDemo3 { public static void main(String[] args) throws Exception {
final CyclicBarrier barrier=new CyclicBarrier(5);
//启用5个线程
for(int i=1;i<=5;i++){
new Thread(new Runnable(){
public void run(){
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("子线程执行!");
try {
barrier.await();//到达屏障
} catch (InterruptedException | BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
}).start(); }
//主线程
barrier.await();//阻塞当前线程直到latch中数值为零才执行
System.out.println("主线程执行!"); } }
countDownLatch和cyclicBarrier区别:
countDownLatch只能使用一次,而CyclicBarrier方法可以使用reset()方法重置,所以CyclicBarrier方法可以能处理更为复杂的业务场景。
我曾经在网上看到一个关于countDownLatch和cyclicBarrier的形象比喻,就是在百米赛跑的比赛中若使用 countDownLatch的话冲过终点线一个人就给评委发送一个人的成绩,10个人比赛发送10次,如果用CyclicBarrier,则只在最后一个人冲过终点线的时候发送所有人的数据,仅仅发送一次,这就是区别。
-END-
java多线程并发控制countDownLatch和cyclicBarrier的使用的更多相关文章
- Java多线程:CountDownLatch、CyclicBarrier 和 Semaphore
场景描述: 多线程设计过程中,经常会遇到需要等待其它线程结束以后再做其他事情的情况. 有几种方案: 1.在主线程中设置一自定义全局计数标志,在工作线程完成时,计数减1.主线程侦测该标志是否为0,一 ...
- Java多线程——其他工具类CyclicBarrier、CountDownLatch和Exchange
CyclicBarrier 适用于:创建一组任务,它们并行地执行任务,然后在进行下一个步骤之前等待,直至所有任务完成.它使得所有的并行任务都将在栅栏处列队,因此可以一致地向前移动. 表示大家彼此等待, ...
- Java计数器之CountDownLatch、CyclicBarrier、Semaphore
在Java里面有几种可以用于控制线程状态的方法,如CountDownLatch计数器.CyclicBarrier循环栅栏.Sempahore信号量.下面就分别演示下他们的使用方法: CountDown ...
- Java并发之CountDownLatch、CyclicBarrier和Semaphore
CountDownLatch 是能使一组线程等另一组线程都跑完了再继续跑:CyclicBarrier 能够使一组线程在一个时间点上达到同步,可以是一起开始执行全部任务或者一部分任务. CountDow ...
- Java多线程-----理解CountDownLatch
CountDownLatch简介 CountDownLatch是在java1.5被引入的,跟它一起被引入的并发工具类还有CyclicBarrier.Semaphore.ConcurrentHa ...
- JAVA中的CountDownLatch、CyclicBarrier、Semaphore的简单测试
因公司需要做一个对于CountDownLatch的分享,特写了此blog. 具体细节可以参见:小结java自带的跟锁相关的一些类 在做这个分享的过程中发现了Main和junit的运行的区别,在另外一个 ...
- java 多线程 day16 CountDownLatch 倒计时计数器
import java.util.concurrent.CountDownLatch;import java.util.concurrent.CyclicBarrier;import java.uti ...
- java多线程对CountDownLatch的使用实例
介绍 CountDownLatch是一个同步辅助类,它允许一个或多个线程一直等待直到其他线程执行完毕才开始执行. 用给定的计数初始化CountDownLatch,其含义是要被等待执行完的线程个数. 每 ...
- Java多线程_同步工具CyclicBarrier
CyclicBarrier概念:CyclicBarrier是多线程中的一个同步工具,它允许一组线程互相等待,直到到达某个公共屏障点.形象点儿说,CyclicBarrier就是一个屏障,要求这一组线程中 ...
随机推荐
- WordPaster-HDwik5.0整合教程
示例下载:http://yunpan.cn/Q9ufQGuFMK34r 1.上传WordPaster文件夹 2.上传upload.php文件,这个文件负责接收控件上传的图片,并保存到uploads文件 ...
- 几种修改Linux主机名的方法
在安装一些系统时,需要修改hostname,比如安装Hadoop时需要修改主机名,而且主机名不能包含下划线. 实际上,主机名分三种(命令hostnamectl或hostnamectl status可查 ...
- MFC载入BMP图片
两步 hBitmap = (HBITMAP)LoadImage(NULL,fullPathName,IMAGE_BITMAP,120,120,LR_LOADFROMFILE);//载入图片 m_pic ...
- _编程语言_C++_std
正常使用 cout << "Count is "<<i<<endl; 含有std std::cout << "Count ...
- [ 9.12 ]CF每日一题系列—— 960B暴力数组
Description: 给你两个数组,顺序一定,问你第一个数组连续的几个值等于下一个数组连续的几个值,然后寻找这个值得最大值,也就是满足就换 Solution: 用两个变量索引,判断即可 #incl ...
- SQL Server主要系统视图说明
SELECT * FROM sys.all_columns --显示属于用户定义对象和系统对象的所有列的联合--https://docs.microsoft.com/zh-cn/sql/relatio ...
- spring cloud学习(二) 调用服务
spring-cloud调用服务有两种方式,一种是Ribbon+RestTemplate, 另外一种是Feign. Ribbon是一个基于HTTP和TCP客户端的负载均衡器,其实feign也使用了ri ...
- spring boot 中使用LUA脚本
编写LUA脚本 该脚本功能:先检查redis中某个key的值是否与期望的值V1一致,如果一致则将其修改为新的值V2并返回true,否则返回false.其实就是CAS. local current = ...
- Swift5 语言参考(五) 语句
在Swift中,有三种语句:简单语句,编译器控制语句和控制流语句.简单语句是最常见的,由表达式或声明组成.编译器控制语句允许程序更改编译器行为的各个方面,并包括条件编译块和行控制语句. 控制流语句用于 ...
- WCF:初识
结构: using System.ServiceModel; namespace MyServices { [ServiceContract] public interface IHomeServic ...