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)并发编程学习> ...
随机推荐
- Web服务器对比介绍
1.Apache Apache是非常强大的老牌Web服务器,具有模块化结构,拥有众多非常成熟稳定的模块,目前仍是使用非常广泛的服务器,但它是基于多进程HTTPServer,需要对每个用户请求创建一个子 ...
- ARTS Week 002
Algorithm Leetcode 2. Add Two Numbers You are given two non-empty linked lists representing two non- ...
- 解决 maven项目在eclipse中debug时看不到源码问题
第一步: 第二步:Configurations 里面的source里面是Default.把Defaul删除,选java project ,然后添加自己的项目 第三步:选中,并用命令跑tomcat 这样 ...
- IntelliJ IDEA 开发git多模块项目
1.clone主项目 填写主仓库地址 2.在项目根目录,初始化子模块,并clone源码 git submodule init git submodule update 3.定位到各个子模块根目录,并切 ...
- spark SQL学习(案例-统计每日uv)
需求:统计每日uv package wujiadong_sparkSQL import org.apache.spark.sql.{Row, SQLContext} import org.apache ...
- IE8下打印内容缩小问题
去掉启动缩小字体填充的设置项勾选 来自为知笔记(Wiz)
- 动态规划入门-01背包问题 - poj3624
2017-08-12 18:50:13 writer:pprp 对于最基础的动态规划01背包问题,都花了我好长时间去理解: poj3624是一个最基本的01背包问题: 题意:给你N个物品,给你一个容量 ...
- HDU 3594 Cactus(仙人掌问题)
http://acm.hdu.edu.cn/showproblem.php?pid=3594 题意: 一个有向图,判断是否强连通和每条边只在一个环中. 思路: 仙人掌问题. 用Tarjan算法判断强连 ...
- 比较好的Json 格式数据
{ "81040753986": [{ "order_info": { "unique_package_reference": " ...
- awardRotate.js
(function($) { var supportedCSS,styles=document.getElementsByTagName("head")[0].style,toCh ...