java多线程并发系列之闭锁(Latch)和栅栏(CyclicBarrier)
-闭锁(Latch)
- 确保某个计算在其需要的所有资源都被初始化之后才继续执行。二元闭锁(包括两个状态)可以用来表示“资源R已经被初始化”,而所有需要R的操作都必须先在这个闭锁上等待。
- 确保某个服务在其依赖的所有其他服务都已经启动之后才启动。
- 等待直到某个操作的所有参与者都就绪在继续执行。(例如:多人游戏中需要所有玩家准备才能开始)
-栅栏(CyclicBarrier)
-例子:两个分别关于CountDownlatch和CyclicBarrier的例子
1、CountDownLatch
工人:
package LatchAndCyclicBarrier;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class Work implements Runnable{
private CountDownLatch downLatch;
private String name;
public Work(CountDownLatch downLatch, String name){
this.downLatch = downLatch;
this.name = name;
}
public void run() {
this.doWork();
try{
TimeUnit.SECONDS.sleep(new Random().nextInt(10));
}catch(InterruptedException ie){
}
System.out.println(this.name + "活干完了!");
this.downLatch.countDown();
}
private void doWork(){
System.out.println(this.name + "正在干活!");
}
}
老板:
package LatchAndCyclicBarrier;
import java.util.concurrent.CountDownLatch;
public class Boss implements Runnable{
private CountDownLatch downLatch;
public Boss(CountDownLatch downLatch){
this.downLatch = downLatch;
}
public void run() {
System.out.println("老板正在等所有的工人干完活......");
try {
this.downLatch.await();
} catch (InterruptedException e) {
}
System.out.println("工人活都干完了,老板开始检查了!");
}
}
测试代码:
package LatchAndCyclicBarrier;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestLatch {
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
CountDownLatch latch = new CountDownLatch(3);
Work w1 = new Work(latch,"张三");
Work w2 = new Work(latch,"李四");
Work w3 = new Work(latch,"王二");
Boss boss = new Boss(latch);
executor.execute(w3);
executor.execute(w2);
executor.execute(w1);
executor.execute(boss);
executor.shutdown();
}
}
执行结果:
李四正在干活!
老板正在等所有的工人干完活......
王二正在干活!
张三正在干活!
李四活干完了!
王二活干完了!
张三活干完了!
工人活都干完了,老板开始检查了!
2、CyclicBarrier
package LatchAndCyclicBarrier;
import java.util.concurrent.CyclicBarrier;
public class CycWork implements Runnable {
private CyclicBarrier cyclicBarrier ;
private String name ;
public CycWork(CyclicBarrier cyclicBarrier,String name)
{
this .name =name;
this .cyclicBarrier =cyclicBarrier;
}
@Override
public void run() {
// TODO Auto-generated method stub
System. out .println(name +"正在打桩,毕竟不轻松。。。。。" );
try {
Thread. sleep(5000);
System. out .println(name +"不容易,终于把桩打完了。。。。" );
cyclicBarrier .await();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
System. out .println(name +":其他逗b把桩都打完了,又得忙活了。。。" );
}
}
测试程序
package LatchAndCyclicBarrier;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CycTest {
public static void main(String[] args)
{
ExecutorService executorpool=Executors. newFixedThreadPool(3);
CyclicBarrier cyclicBarrier= new CyclicBarrier(3);
CycWork work1= new CycWork(cyclicBarrier, "张三" );
CycWork work2= new CycWork(cyclicBarrier, "李四" );
CycWork work3= new CycWork(cyclicBarrier, "王五" );
executorpool.execute(work1);
executorpool.execute(work2);
executorpool.execute(work3);
executorpool.shutdown();
}
}
运行结果:
李四正在打桩,毕竟不轻松。。。。。
张三正在打桩,毕竟不轻松。。。。。
王五正在打桩,毕竟不轻松。。。。。
李四不容易,终于把桩打完了。。。。
张三不容易,终于把桩打完了。。。。
王五不容易,终于把桩打完了。。。。
王五:其他逗b把桩都打完了,又得忙活了。。。
李四:其他逗b把桩都打完了,又得忙活了。。。
张三:其他逗b把桩都打完了,又得忙活了。。。
CountDownlatch和CyclicBarrierde 源码部分
1、CountDownLatch中的两个关键方法
public void countDown() { //对计数器减一 表示有一个事件已经发生了
sync.releaseShared(1);
}
public void await() throws InterruptedException { //等到计数器为0
sync.acquireSharedInterruptibly(1);
}
public final void acquireSharedInterruptibly (int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
public final boolean releaseShared (int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true ;
}
return false ;
}
protected boolean tryReleaseShared (int arg) {
throw new UnsupportedOperationException();
}
2、CyclicBarrier中的await()方法
public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen;
}
}
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
final ReentrantLock lock = this.lock;
lock.lock();
try {
final Generation g = generation;
if (g.broken)
throw new BrokenBarrierException();
if (Thread.interrupted()) {
breakBarrier();
throw new InterruptedException();
}
int index = --count;
if (index == 0) { // tripped
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
nextGeneration();
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
}
// loop until tripped, broken, interrupted, or timed out
for (;;) {
try {
if (!timed)
trip.await();
else if (nanos > 0L)
nanos = trip.awaitNanos(nanos);
} catch (InterruptedException ie) {
if (g == generation && ! g.broken) {
breakBarrier();
throw ie;
} else {
// We're about to finish waiting even if we had not
// been interrupted, so this interrupt is deemed to
// "belong" to subsequent execution.
Thread.currentThread().interrupt();
}
}
if (g.broken)
throw new BrokenBarrierException();
if (g != generation)
return index;
if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
}
count = parties;
提到 parties就不得不看看构造函数了
public CyclicBarrier(int parties) {
this(parties, null);
}
如上例子,我们构造了CyclicBarrier(3)那么此时的 count值为3,接着dowait源码,当index==0时,后面执行的
final Runnable command = barrierCommand;
其实是可以设置的,这个Runnable可以传进来,当我们希望所有线程都达到某一时刻之后,用什么线程执行接下来的工作,当没有传Runnable进来时,就继续执行(唤醒其他线程),否则就runnable.run()(唤醒其他线程之前执行)
java多线程并发系列之闭锁(Latch)和栅栏(CyclicBarrier)的更多相关文章
- Java多线程并发系列之闭锁(Latch)和栅栏(CyclicBarrier)
JAVA并发包中有三个类用于同步一批线程的行为,分别是闭锁(Latch),信号灯(Semaphore)和栅栏(CyclicBarrier).本贴主要说明闭锁(Latch)和栅栏(CyclicBarri ...
- 并发编程 04——闭锁CountDownLatch 与 栅栏CyclicBarrier
Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭 ...
- java 多线程并发系列之 生产者消费者模式的两种实现
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据 ...
- java高并发系列 - 第16天:JUC中等待多线程完成的工具类CountDownLatch,必备技能
这是java高并发系列第16篇文章. 本篇内容 介绍CountDownLatch及使用场景 提供几个示例介绍CountDownLatch的使用 手写一个并行处理任务的工具类 假如有这样一个需求,当我们 ...
- 从火箭发场景来学习Java多线程并发闭锁对象
从火箭发场景来学习Java多线程并发闭锁对象 倒计时器场景 在我们开发过程中,有时候会使用到倒计时计数器.最简单的是:int size = 5; 执行后,size—这种方式来实现.但是在多线程并发的情 ...
- Java高并发系列——检视阅读
Java高并发系列--检视阅读 参考 java高并发系列 liaoxuefeng Java教程 CompletableFuture AQS原理没讲,需要找资料补充. JUC中常见的集合原来没讲,比如C ...
- Java 多线程并发编程一览笔录
Java 多线程并发编程一览笔录 知识体系图: 1.线程是什么? 线程是进程中独立运行的子任务. 2.创建线程的方式 方式一:将类声明为 Thread 的子类.该子类应重写 Thread 类的 run ...
- Java多线程并发07——锁在Java中的实现
上一篇文章中,我们已经介绍过了各种锁,让各位对锁有了一定的了解.接下来将为各位介绍锁在Java中的实现.关注我的公众号「Java面典」了解更多 Java 相关知识点. 在 Java 中主要通过使用sy ...
- [转]Java多线程干货系列—(一)Java多线程基础
Java多线程干货系列—(一)Java多线程基础 字数7618 阅读1875 评论21 喜欢86 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们 ...
随机推荐
- 数组初始化 memset fill
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #in ...
- RabbitMQ的生产者和消费者
低级错误:启动程序的时候报错:socket close: 原因在配置文件中写的端口是:15672,应该是5672: client端通信口5672管理口15672server间内部通信口25672erl ...
- Openstack 错误日志查看方法
openstack错误日志查看方法 https://blog.csdn.net/ZanShichun/article/details/72672945
- java基础基础总结----- RunTime
- 比特币全节点(bitcoind) eth 全节点
运行全节点的用途: 1.挖矿 2.钱包 运行全节点,可以做关于btc的任何事情,例如创建钱包地址.管理钱包地址.发送交易.查询全网的交易信息等等 选个节点钱包:bitcoind 1.配置文件: ...
- transform 属性之 transform-origin与顺序问题
transform属性之 transform-origin 针对transform中的几种值的先后顺序 transform值的先后顺序: 注意: 当我们在旋转后再进行位移的时候,其实是按照旋转后的坐标 ...
- SHELL (4) —— 变量的数值计算实践
摘自:Oldboy Linux运维——SHELL编程实战 利用(())双括号进行比较及判断: [root@yeebian ~]# echo $((3<8)) 1 #1表示真. [root@yee ...
- bzoj千题计划200:bzoj3106: [cqoi2013]棋盘游戏
http://www.lydsy.com/JudgeOnline/problem.php?id=3106 白棋如果第一步不能赢,那么一定输 因为可以黑棋走的距离比白棋大,黑棋可以下一步吃掉白棋,也可以 ...
- Struts2_day03
一.上节回顾 1 在action获取表单提交数据 (1)使用ActionContext类获取 (2)使用ServletActionContext类获取 (3)接口注入 2 结果配置 (1)全局结果页面 ...
- ASP.net 控件实现数据级联
今天我们来一起用ASP.net实现一个级联,这个小不点应该是会经常用到的的. 咱们简单的画两个窗体.文本框会根据下拉框所选的内容显示不同的内容. 具体实现效果如下 步骤一: 准备工作,建立相应的数据库 ...