Java并发编程之CountDownLatch,CyclicBarrier实现一组线程相互等待、唤醒
java多线程应用场景不少,有时自己编写代码又不太容易实现,好在concurrent包提供了不少实现类,还有google的guava包更是提供了一些最佳实践,这让我们在面对一些多线程的场景时,有了不少的选择。
这里主要是看几个涉及到多线程等待的工具类。
一 CountDownLatch 一个或多个线程等待其他线程达到某一个目标后,再进行自己的下一步工作。而被等待的“其他线程”达到这个目标后,也继续自己下面的任务
public CountDownLatch(int count) { }; //参数count为计数值
public void await() throws InterruptedException { }; //调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { }; //和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
public void countDown() { }; //将count值减1
工作原理就是让“其他线程”在合适的地方进行await等待,直到所有线程达到了某一个目标,然后再一起释放。
import java.util.Random;
import java.util.concurrent.CountDownLatch;
/**
* Created by wuwf on 17/7/17.
* 一个线程或多个线程等待其他线程运行达到某一目标后进行自己的下一步工作,而被等待的“其他线程”达到这个目标后继续自己下面的任务。
* <p/>
*
*/
public class TestCountDownLatch {
private CountDownLatch countDownLatch = new CountDownLatch(4);
public static void main(String[] args) {
TestCountDownLatch testCountDownLatch = new TestCountDownLatch();
testCountDownLatch.begin();
}
/**
* 运动员
*/
private class Runner implements Runnable {
private int result;
public Runner(int result) {
this.result = result;
}
@Override
public void run() {
try {
//模拟跑了多少秒,1-3之间随机一个数
Thread.sleep(result * 1000);
System.out.println("运动员" + Thread.currentThread().getId() + "跑了" + result + "秒");
//跑完了就计数器减1
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void begin() {
System.out.println("赛跑开始");
Random random = new Random(System.currentTimeMillis());
for (int i = 0; i < 4; i++) {
//随机设置每个运动员跑多少秒结束
int result = random.nextInt(3) + 1;
new Thread(new Runner(result)).start();
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("所有人都跑完了,裁判开始算成绩");
}
}
这段代码就是一个主线程,等待其他多个子线程完成某个任务后,再去执行下面的逻辑。
模拟并发的代码
import java.util.concurrent.CountDownLatch;
/**
* Created by wuwf on 17/7/18.
* 模拟N个线程同时启动
*/
public class TestManyThread {
private CountDownLatch countDownLatch = new CountDownLatch(200);
public static void main(String[] args) {
new TestManyThread().begin();
}
public void begin() {
for (int i = 0; i < 200; i++) {
new Thread(new UserThread()).start();
countDownLatch.countDown();
}
try {
Thread.sleep(2000);
System.out.println("线程并发");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private class UserThread implements Runnable {
@Override
public void run() {
try {
//等待所有线程
countDownLatch.await();
//TODO 在这里做客户端请求,譬如访问数据库之类的操作
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
需要注意,上面两个例子是不同的方式,一个是主线程等待其他线程达到某个目标后,自己再去完成一件事;第二个例子是多个线程达到某个目标后,继续完成各自的后续任务。
其中由第二个例子引申出下一个并发工具类。
二 CyclicBarrier 实现让一组线程等待至某个状态之后再全部同时执行,而且当所有等待线程被释放后,CyclicBarrier可以被重复使用。
public CyclicBarrier(int parties, Runnable barrierAction) {
}
public CyclicBarrier(int parties) {
}
parties代表让多少个线程等待,Runnable属性是一个新线程,代表所有线程达到状态、等待完毕后,会执行的任务。
同样的也有两个await方法
public int await() throws InterruptedException, BrokenBarrierException { };
public int await(long timeout, TimeUnit unit)throws InterruptedException,BrokenBarrierException,TimeoutException { };
第一个代表线程挂起开始等待,一直等到达到目标状态,第二个代表等待一段指定的时间后,如果还没释放,就直接继续执行,不await了。
import java.util.concurrent.CyclicBarrier;
/**
* Created by wuwf on 17/7/18.
*/
public class TestCyclicBarrier {
private CyclicBarrier cyclicBarrier = new CyclicBarrier(5);
public static void main(String[] args) {
new TestCyclicBarrier().begin();
}
public void begin() {
for (int i = 0; i < 5; i++) {
new Thread(new Student()).start();
}
}
private class Student implements Runnable {
@Override
public void run() {
try {
System.out.println("学生" + Thread.currentThread().getId() + "正在赶往XX饭店的路上");
Thread.sleep(2000);
//到了就等着,等其他人都到了,就进饭店
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("大家都到了,进去吃饭吧!");
}
}
}
Java并发编程之CountDownLatch,CyclicBarrier实现一组线程相互等待、唤醒的更多相关文章
- Java 并发编程中的 CyclicBarrier 用于一组线程互相等待
Java 5 引入的 Concurrent 并发库软件包中的 CyclicBarrier 是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point) ...
- Java并发编程之CountDownLatch
一.场景描述 在多线程程序设计中,经常会遇到一个线程等待一个或多个线程的场景 例如:百米赛跑,十名运动员同时起跑,由于速度的快慢,肯定有先到达和后到达的,而终点有个统计成绩的仪器,当所有选手到达终点时 ...
- Java并发编程之CountDownLatch的用法
一.含义 CountDownLatch类位于java.util.concurrent包下,利用它可以实现类似计数器的功能.CountDownLatch是一个同步的辅助类,它可以允许一个或多个线程等待, ...
- Java并发编程之CyclicBarrier
一.场景描述 有四个游戏玩家玩游戏,游戏有三个关卡,每个关卡必须要所有玩家都到达后才能允许通过.其实这个场景里的玩家中如果有玩家A先到了关卡1,他必须等到其他所有玩家都到达关卡1时才能通过,也就是说线 ...
- Java并发编程之CAS
CAS(Compare and swap)比较和替换是设计并发算法时用到的一种技术.简单来说,比较和替换是使用一个期望值和一个变量的当前值进行比较,如果当前变量的值与我们期望的值相等,就使用一个新值替 ...
- Java并发编程之CAS第一篇-什么是CAS
Java并发编程之CAS第一篇-什么是CAS 通过前面几篇的学习,我们对并发编程两个高频知识点了解了其中的一个—volatitl.从这一篇文章开始,我们将要学习另一个知识点—CAS.本篇是<凯哥 ...
- Java并发编程之CAS二源码追根溯源
Java并发编程之CAS二源码追根溯源 在上一篇文章中,我们知道了什么是CAS以及CAS的执行流程,在本篇文章中,我们将跟着源码一步一步的查看CAS最底层实现原理. 本篇是<凯哥(凯哥Java: ...
- Java并发编程之CAS第三篇-CAS的缺点及解决办法
Java并发编程之CAS第三篇-CAS的缺点 通过前两篇的文章介绍,我们知道了CAS是什么以及查看源码了解CAS原理.那么在多线程并发环境中,的缺点是什么呢?这篇文章我们就来讨论讨论 本篇是<凯 ...
- Java并发编程之set集合的线程安全类你知道吗
Java并发编程之-set集合的线程安全类 Java中set集合怎么保证线程安全,这种方式你知道吗? 在Java中set集合是 本篇是<凯哥(凯哥Java:kagejava)并发编程学习> ...
随机推荐
- ssh-keygen 的 详解
为了让两个Linux机器之间使用ssh不需要用户名和密码.所以采用了数字签名RSA或者DSA来完成这个操作. 模型分析 假设 A (192.168.20.59)为客户机器,B(192.168.20.6 ...
- ThinkPHP将上传问件添加到数据库
<?php namespace Home\Controller; /***************** use Think\Controller; ****命名空间****/ class Mes ...
- PHP中的_FILE_和_DIR_的区别
<?php$dir = dirname(__FILE__);?>在PHP5.3中,增加了一个新的常量__DIR__,指向当前执行的PHP脚本所在的目录.例如当前执行的PHP文件为 /www ...
- GCC嵌入式汇编(内嵌汇编)入门
GCC嵌入式汇编(内嵌汇编)入门 1. 入门 在C中嵌入汇编的最大问题是如何将C语言变量与指令操作数相关联.当然,gcc都帮我们想好了.下面是是一个简单例子. asm("fsinx %1, ...
- 01_HBase概述
1. HBase在Hadoop生态圈中的位置 问题:HBase 是什么,用在哪里,解决什么样的问题? 解答: 1)简单来说, HBase 是一种类似于面向列的分布式数据库(集群), 底层利用HDFS ...
- 转 : JBoss Web和 Tomcat的区别
JBoss Web和 Tomcat的区别 在Web2.0的浪潮中,各种页面技术和框架不断涌现,为服务器端的基础架构提出了更高的稳定性和可扩展性的要求.近年来,作为开源中间件的全 球领导者,JBoss在 ...
- 新东方雅思词汇---9.1、sist
新东方雅思词汇---9.1.sist 一.总结 一句话总结: 站 resist 英 [rɪ'zɪst] 美 [rɪ'zɪst] vi. 抵抗,抗拒:忍耐 vt. 抵抗:忍耐,忍住 n. [助剂] ...
- 使用Netty做WebSocket服务端
使用Netty搭建WebSocket服务器 1.WebSocketServer.java public class WebSocketServer { private final ChannelGro ...
- ubuntu16.04 安装以及要做的事情
1.安装ubuntu 选择安装时更新,以及MP3.图形等:然后选择分区(ext4)(安装时需先进入虚拟系统连上网,输入清华net账号),分区情况按照下图来,swap为临时用的内存分区,可以不要: 选择 ...
- oracle 11g安装过程中问题:移动bin\oralbac11.dll 到bin\oralbac11.dll.dbl出错
解决方法: 直接找到oralbac11.dll.dbl这个文件,将其删除即可. http://blog.sina.com.cn/s/blog_51beaf0e0101000v.html