CountDownLatch 的使用场景:在主线程中开启多线程去并行执行任务,并且主线程需要等待所有子线程执行完毕后汇总返回结果。

我把源码中的英文注释全部删除,写上自己的注释。就剩下 70 行不到的代码,很简单了。

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer; public class CountDownLatch {
// 自定义一个属性,继承 抽象队列同步器
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L; Sync(int count) {
setState(count);
} int getCount() {
return getState();
} @Override
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
} @Override
protected boolean tryReleaseShared(int releases) {
for (;;) {
int c = getState();
if (c == 0) {
return false;
}
int nextc = c-1;
if (compareAndSetState(c, nextc)) {
return nextc == 0;
}
}
}
}
//定义私有属性,该类继承 抽象队列同步器
private final java.util.concurrent.CountDownLatch.Sync sync; // 构造方法,传入数字,用于倒计数
public CountDownLatch(int count) {
if (count < 0) {
throw new IllegalArgumentException("count < 0");
}
this.sync = new java.util.concurrent.CountDownLatch.Sync(count);
}
// 阻塞当前线程,直到count=0才唤醒线程
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
// 阻塞当前线程,直到count=0才唤醒线程。
// 设置定时时间到了,也会唤醒线程。
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
//count 减 1
public void countDown() {
sync.releaseShared(1);
}
//获取 count
public long getCount() {
return sync.getCount();
}
//toString方法,获取字符串
public String toString() {
return super.toString() + "[Count = " + sync.getCount() + "]";
}
}

我用这个CountDownLatch来实现多线程执行任务,合并结果返回。

//创建线程池
ExecutorService pool = Executors.newCachedThreadPool();
//定义集合存储结果
List<Object> values = new ArrayList<>();
//定义倒计数器
CountDownLatch count = new CountDownLatch(2); //线程池执行任务1
pool.submit(new Runnable() {
@Override
public void run() {
try {
//线程池进行计算1,得到结果1。
String value1 = "结果1";
//把结果加入共享变量中。
values.add(value1);
} catch (Exception e) {
e.printStackTrace();
}finally {
//finally 中保证一定会执行 减1
//计数器减 1
count.countDown();
} }
}); //线程池执行任务2
pool.submit(new Runnable() {
@Override
public void run() {
try {
//线程池进行计算2,得到结果2。
String value2 = "结果2";
//把结果加入共享变量中。
values.add(value2);
} catch (Exception e) {
e.printStackTrace();
}finally {
//finally 中保证一定会执行 减1
//计数器减 1
count.countDown();
} }
});
//线程阻塞等待
count.await(); //返回多线程执行的结果。
return values;

  多线程并发编程,就是这么简单!不用Callable,也能获取到线程池的返回值哦。

JAVA并发编程之倒计数器CountDownLatch的更多相关文章

  1. Java并发编程-JUC-CountDownLatch 倒计数门闩器-等待多线程完成再放行 -一次性使用

    如题 (总结要点) CountDownLatch 倒计数门闩器, 让1-n-1个线程等待其他多线程完成工作. (Excel的多个Sheet的解析,最终等待解析完毕后;要实现主线程等待所有线程完成she ...

  2. 并发编程-concurrent指南-计数器CountDownLatch

    java.util.concurrent.CountDownLatch 是一个并发构造,它允许一个或多个线程等待一系列指定操作的完成. CountDownLatch 以一个给定的数量初始化.count ...

  3. Java并发编程:Semaphore、CountDownLatch、CyclicBarrier

    首先我们来实现一个功能:当我们启动一个系统的时候需要初始化许多数据,这时候我们可能需要启动很多线程来进行数据的初始化,只有这些系统初始化结束之后才能够启动系统.其实在Java的类库中已经提供了Sema ...

  4. Java并发编程_wait/notify和CountDownLatch的比较(三)

     1.wait/notify方法 package sync; import java.util.ArrayList; import java.util.List; public class WaitA ...

  5. 【Java并发编程实战】-----“J.U.C”:CountDownlatch

    上篇博文([Java并发编程实战]-----"J.U.C":CyclicBarrier)LZ介绍了CyclicBarrier.CyclicBarrier所描述的是"允许一 ...

  6. Java并发编程:CountDownLatch、CyclicBarrier和Semaphore

    Java并发编程:CountDownLatch.CyclicBarrier和Semaphore 在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch ...

  7. Java并发编程的4个同步辅助类(CountDownLatch、CyclicBarrier、Semaphore、Phaser)

    我在<JDK1.5引入的concurrent包>中,曾经介绍过CountDownLatch.CyclicBarrier两个类,还给出了CountDownLatch的演示案例.这里再系统总结 ...

  8. Java并发编程的4个同步辅助类(CountDownLatch、CyclicBarrier、Semphore、Phaser)

    我在<jdk1.5引入的concurrent包>中,曾经介绍过CountDownLatch.CyclicBarrier两个类,还给出了CountDownLatch的演示案例.这里再系统总结 ...

  9. 14、Java并发编程:CountDownLatch、CyclicBarrier和Semaphore

    Java并发编程:CountDownLatch.CyclicBarrier和Semaphore 在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch ...

随机推荐

  1. Product Backlog:终极任务清单

    健康的Product Backlog就像一个健康的人那样:整洁有序.组织合理.公开透明.一个按照优先级顺序排好的敏捷Backlog不仅能够简化发版和迭代计划,还能够对团队计划去做的所有工作进行细致规划 ...

  2. 二分查找(Binary Search)的递归和非递归

    Binary Search 有时候我们也把它叫做二进制查找 是一种较为高效的再数组中查找目标元素的方法 我们可以通过递归和非递归两种方式来实现它 //非递归 public static int bin ...

  3. 第一个SpringBoot

    Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.用我 ...

  4. 微服务-springboot多环境配置(开发生产测试环境切换)

    springboot根据spring.profiles.active会去寻找应该加载开发环境配置还是生产环境配置 application.properties #生产环境,开发环境,测试环境切换 pr ...

  5. Vue兄弟组件(非父子组件)状态共享与传值

      前言:网上大部分文章写的有点乱,很少有讲得易懂的文章. 所以,我写了篇在我能看得懂的基础上又照顾到大家的文章 =.= 作者:X1aoYE 备注:此文原创,转载请注明~  内容里的<br> ...

  6. HDU 1542:Atlantis(扫描线+线段树 矩形面积并)***

    题目链接 题意 给出n个矩形,求面积并. 思路 使用扫描线,我这里离散化y轴,按照x坐标从左往右扫过去.离散化后的y轴可以用线段树维护整个y上面的线段总长度,当碰到扫描线的时候,就可以统计面积.这里要 ...

  7. ZOJ 3795:Grouping(缩点+最长路)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5303 题意:有n个人m条边,每条边有一个u,v,代表u的年龄大于等于v,现在要 ...

  8. Altium Designer设计PCB--如何设置铺铜与导线或过孔的间距

    笑话: 到银行汇款,车临时停路边上. 为了怕交警罚就把朋友留下看车,跟他说有查车的过来了告诉我一声. 进去几分钟果然有交警来了. 那个朋友风风火火地闯进银行大声吼道:“大哥,警察来了,快走啊!” 偌大 ...

  9. C# Socket 简单的控制台案例

    一.服务器端 1. 实例化并设置socket实例对象 a.创建ip地址和端口 b.绑定监听地址 c.设置一下允许同时访问数 2. 监听连接 a.通过启动一个新的线程执行,这样主线程不会假死(启动线程, ...

  10. 基于SpringCloud的微服务架构实战案例项目

    QuickStart 基于SpringCloud体系实现,简单购物流程实现,满足基本功能:注册.登录.商品列表展示.商品详情展示.订单创建.详情查看.订单支付.库存更新等等. github源码地址:h ...