CyclicBarrier的作用是,线程进入等待后,需要达到一定数量的等待线程后,再一次性开放通行。

  • CyclicBarrier(int, Runnable)
    构造方法,参数1为通行所需的线程数量,参数2为条件满足时的监听器。
  • int await()/int await(long, TimeUnit)
    线程进入等待,并返回一个进入等待时的倒计索引。
  • int getParties()
    通行所需的线程数量
  • int getNumberWaiting()
    当前线程数量
  • boolean isBroken()
    本批次是否已经终止
  • reset()
    释放本批次通行,并重新接收下一批线程进入。

源码分析:

/**
* @since 1.5
* @see CountDownLatch
*
* @author Doug Lea
*/
public class CyclicBarrier { public CyclicBarrier(int parties) {
this(parties, null);
} public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0)
throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
} private static class Generation {
boolean broken = false;
} private final ReentrantLock lock = new ReentrantLock();
private final Condition trip = lock.newCondition();
private final int parties;
private final Runnable barrierCommand;
private Generation generation = new Generation(); private int count; private void nextGeneration() {
// 通知本批次所有线程可通行
trip.signalAll();
// 重置计数器
count = parties;
// 重建批次对象,即不同批次使用不同对象
generation = new Generation();
} private void breakBarrier() {
// 标示本批次已终止
generation.broken = true;
// 重置计数器
count = parties;
// 通知本批次所有线程可通行
trip.signalAll();
} public int getParties() {
// 返回通行所需的线程数量
return parties;
} public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe);
}
} public int await(long timeout, TimeUnit unit) throws InterruptedException,
BrokenBarrierException, TimeoutException {
return dowait(true, unit.toNanos(timeout));
} 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) {
// 观察监听器是否正常运行结束
boolean ranAction = false;
try {
// 执行监听器
final Runnable command = barrierCommand;
if (command != null)
command.run();
// 标记正常运行
ranAction = true;
// 通知所有线程并重置
nextGeneration();
// 返回索引
return 0;
} finally {
// 如果监听器是运行时异常结束,则终止本批次
if (!ranAction)
breakBarrier();
}
} 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 {
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();
}
} public boolean isBroken() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
// 返回本批次是否已经终止
return generation.broken;
} finally {
lock.unlock();
}
} public void reset() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
// 终止本批次
breakBarrier();
// 开始下一批
nextGeneration();
} finally {
lock.unlock();
}
} public int getNumberWaiting() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
// 返回本批次等待中的线程数量
return parties - count;
} finally {
lock.unlock();
}
}
}

多线程条件通行工具——CyclicBarrier的更多相关文章

  1. 多线程条件通行工具——AbstractQueuedSynchronizer

    本文原创,转载请注明出处! 参考文章: <"JUC锁"03之 公平锁(一)> <"JUC锁"03之 公平锁(二)> AbstractOw ...

  2. 多线程条件通行工具——CountDownLatch

    CountDownLatch的作用是,线程进入等待后,需要计数器达到0才能通行. CountDownLatch(int)构造方法,指定初始计数. await()等待计数减至0. await(long, ...

  3. 多线程条件通行工具——Semaphore

    Semaphore的作用是,限制线程通行的数量,如果线程进入时达到通行数量,便等待其它正在通行的线程释放. acquire()获取通行 release()释放通行 availablePermits() ...

  4. Java多线程_同步工具CyclicBarrier

    CyclicBarrier概念:CyclicBarrier是多线程中的一个同步工具,它允许一组线程互相等待,直到到达某个公共屏障点.形象点儿说,CyclicBarrier就是一个屏障,要求这一组线程中 ...

  5. 并发工具CyclicBarrier源码分析及应用

      本文首发于微信公众号[猿灯塔],转载引用请说明出处 今天呢!灯塔君跟大家讲: 并发工具CyclicBarrier源码分析及应用 一.CyclicBarrier简介 1.简介 CyclicBarri ...

  6. JAVA多线程提高十:同步工具CyclicBarrier与CountDownLatch

    今天继续学习其它的同步工具:CyclicBarrier与CountDownLatch 一.CyclicBarrier CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公 ...

  7. JAVA多线程学习十三 - 同步工具CyclicBarrier与CountDownLatch

    一.CyclicBarrier CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).在涉及一组固定大小的线程的程序 ...

  8. 并发工具CyclicBarrier

    想想一下这样一个场景,有多个人需要过河,河上有一条船,船要等待满10个人才过河,过完河后每个人又各自行动. 这里的人相当于线程,注意这里,每个线程运行到一半的时候,它就要等待一个条件,即船满过河的条件 ...

  9. java多线程并发控制countDownLatch和cyclicBarrier的使用

    java主线程等待所有子线程执行完毕在执行,这个需求其实我们在工作中经常会用到,比如用户下单一个产品,后台会做一系列的处理,为了提高效率,每个处理都可以用一个线程来执行,所有处理完成了之后才会返回给用 ...

随机推荐

  1. Jade模板引擎让你飞

    写在前面:现在jade改名成pug了 一.安装 npm install jade 二.基本使用 1.简单使用 p hello jade! 渲染后: <p>hello jade!</p ...

  2. [APUE]UNIX进程的环境(下)

    一.共享库 共享库使得可执行文件中不再需要包含常用的库函数,而只需在所有进程都可存取的存储区中保存这种库例程的一个副本.程序第一次执行的时候或第一次调用某个库函数的时候,用动态链接方法将程序与共享库函 ...

  3. TODO:搭建Laravel VueJS SemanticUI

    TODO:搭建Laravel VueJS SemanticUI Laravel是一套简洁.优雅的PHP开发框架(PHP Web Framework).可以让你从面条一样杂乱的代码中解脱出来:它可以帮你 ...

  4. JdbcTemplate+PageImpl实现多表分页查询

    一.基础实体 @MappedSuperclass public abstract class AbsIdEntity implements Serializable { private static ...

  5. Android如何制作漂亮的自适布局的键盘

    最近做了个自定义键盘,但面对不同分辨率的机型其中数字键盘不能根据界面大小自已铺满,但又不能每种机型都做一套吧,所以要做成自适应,那这里主讲思路. 这里最上面的titlebar高度固定,下面输入的金额高 ...

  6. 漫谈TCP

    不得不承认,tcp是一个非常复杂的协议.它包含了RFC793及之后的一些协议.能把tcp的所有方面面面具到地说清楚,本身就是个很复杂的事情.如果再讲得枯燥,那么就会更让人昏昏欲睡了.本文希望能尽量用稍 ...

  7. 设计模式C#合集--工厂方法模式

    简单工厂,代码: public interface ISpeak { public void Say(); } public class Hello : ISpeak { public void Sa ...

  8. 【干货分享】流程DEMO-制度发文和干部任免

    流程名: 制度发文和干部任免  业务描述: 当员工在该出勤的工作日出勤但漏打卡时,于一周内填写补打卡申请.  流程相关文件: 流程包.xml  流程说明: 直接导入流程包文件,即可使用本流程  表单: ...

  9. Android菜单项内容大全

    一.介绍: 菜单是许多应用中常见的用户界面组件. Android3.0版本以前,Android设备会提供一个专用"菜单"按钮呈现常用的一些用户操作, Android3.0版本以后, ...

  10. 参数探测(Parameter Sniffing)影响存储过程执行效率解决方案

    如果SQL query中有参数,SQL Server 会创建一个参数嗅探进程以提高执行性能.该计划通常是最好的并被保存以重复利用.只是偶尔,不会选择最优的执行计划而影响执行效率. SQL Server ...