java并发中CountDownLatch的使用
java并发中CountDownLatch的使用
在java并发中,控制共享变量的访问非常重要,有时候我们也想控制并发线程的执行顺序,比如:等待所有线程都执行完毕之后再执行另外的线程,或者等所有线程都准备好了才开始所有线程的执行等。
这个时候我们就可以使用到CountDownLatch。
简单点讲,CountDownLatch存有一个放在QueuedSynchronizer中的计数器。当调用countdown() 方法时,该计数器将会减一。然后再调用await()来等待计数器归零。
private static final class Sync extends AbstractQueuedSynchronizer {
...
}
private final Sync sync;
public void countDown() {
sync.releaseShared(1);
}
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
下面我们举两个使用的例子:
主线程等待子线程全都结束之后再开始运行
这里我们定义子线程类,在子线程类里面,我们传入一个CountDownLatch用来计数,然后在子线程结束之前,调用该CountDownLatch的countDown方法。最后在主线程中调用await()方法来等待子线程结束执行。
@Slf4j
public class MainThreadWaitUsage implements Runnable {
private List<String> outputScraper;
private CountDownLatch countDownLatch;
public MainThreadWaitUsage(List<String> outputScraper, CountDownLatch countDownLatch) {
this.outputScraper = outputScraper;
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
outputScraper.add("Counted down");
countDownLatch.countDown();
}
}
看下怎么调用:
@Test
public void testCountDownLatch()
throws InterruptedException {
List<String> outputScraper = Collections.synchronizedList(new ArrayList<>());
CountDownLatch countDownLatch = new CountDownLatch(5);
List<Thread> workers = Stream
.generate(() -> new Thread(new MainThreadWaitUsage(outputScraper, countDownLatch)))
.limit(5)
.collect(toList());
workers.forEach(Thread::start);
countDownLatch.await();
outputScraper.add("Latch released");
log.info(outputScraper.toString());
}
执行结果如下:
07:37:27.388 [main] INFO MainThreadWaitUsageTest - [Counted down, Counted down, Counted down, Counted down, Counted down, Latch released]
等待所有线程都准备好再一起执行
上面的例子中,我们是主线程等待子线程,那么在这个例子中,我们将会看看怎么子线程一起等待到准备好的状态,再一起执行。
思路也很简单,在子线程开始之后,将等待的子线程计数器减一,在主线程中await该计数器,等计数器归零之后,主线程再通知子线程运行。
public class ThreadWaitThreadUsage implements Runnable {
private List<String> outputScraper;
private CountDownLatch readyThreadCounter;
private CountDownLatch callingThreadBlocker;
private CountDownLatch completedThreadCounter;
public ThreadWaitThreadUsage(
List<String> outputScraper,
CountDownLatch readyThreadCounter,
CountDownLatch callingThreadBlocker,
CountDownLatch completedThreadCounter) {
this.outputScraper = outputScraper;
this.readyThreadCounter = readyThreadCounter;
this.callingThreadBlocker = callingThreadBlocker;
this.completedThreadCounter = completedThreadCounter;
}
@Override
public void run() {
readyThreadCounter.countDown();
try {
callingThreadBlocker.await();
outputScraper.add("Counted down");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
completedThreadCounter.countDown();
}
}
}
看下怎么调用:
@Test
public void testCountDownLatch()
throws InterruptedException {
List<String> outputScraper = Collections.synchronizedList(new ArrayList<>());
CountDownLatch readyThreadCounter = new CountDownLatch(5);
CountDownLatch callingThreadBlocker = new CountDownLatch(1);
CountDownLatch completedThreadCounter = new CountDownLatch(5);
List<Thread> workers = Stream
.generate(() -> new Thread(new ThreadWaitThreadUsage(
outputScraper, readyThreadCounter, callingThreadBlocker, completedThreadCounter)))
.limit(5)
.collect(toList());
workers.forEach(Thread::start);
readyThreadCounter.await();
outputScraper.add("Workers ready");
callingThreadBlocker.countDown();
completedThreadCounter.await();
outputScraper.add("Workers complete");
log.info(outputScraper.toString());
}
输出结果如下:
07:41:47.861 [main] INFO ThreadWaitThreadUsageTest - [Workers ready, Counted down, Counted down, Counted down, Counted down, Counted down, Workers complete]
停止CountdownLatch的await
如果我们调用await()方法,该方法将会等待一直到count=0才结束。但是如果在线程执行过程中出现了异常,可能导致countdown方法执行不了。那么await()方法可能会出现无限等待的情况。
这个时候我们可以使用:
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
本文的例子可以参考https://github.com/ddean2009/learn-java-concurrency/tree/master/CountDownLatch
更多教程请参考 flydean的博客
java并发中CountDownLatch的使用的更多相关文章
- 深入浅出Java并发中的CountDownLatch
1. CountDownLatch 正如每个Java文档所描述的那样,CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行.在Java并发中 ...
- java并发初探CountDownLatch
java并发初探CountDownLatch CountDownLatch是同步工具类能够允许一个或者多个线程等待直到其他线程完成操作. 当前前程A调用CountDownLatch的await方法进入 ...
- java并发中ExecutorService的使用
文章目录 创建ExecutorService 为ExecutorService分配Tasks 关闭ExecutorService Future ScheduledExecutorService Exe ...
- java并发中的Synchronized关键词
文章目录 为什么要同步 Synchronized关键词 Synchronized Instance Methods Synchronized Static Methods Synchronized B ...
- JAVA并发,CountDownLatch使用
该文章转自:http://www.itzhai.com/the-introduction-and-use-of-a-countdownlatch.html CountDownLatch 1.类介绍 一 ...
- Java并发——结合CountDownLatch源码、Semaphore源码及ReentrantLock源码来看AQS原理
前言: 如果说J.U.C包下的核心是什么?那我想答案只有一个就是AQS.那么AQS是什么呢?接下来让我们一起揭开AQS的神秘面纱 AQS是什么? AQS是AbstractQueuedSynchroni ...
- Java并发中的CopyOnWrite容器
Copy-On-Write简称COW,是一种用于程序设计中的优化策略.其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改, ...
- Java并发编程-CountDownLatch
基于AQS的前世今生,来学习并发工具类CountDownLatch.本文将从CountDownLatch的应用场景.源码原理解析来学习这个并发工具类. 1. 应用场景 CountDownLatch是并 ...
- 一起来看看java并发中volatile关键字的神奇之处
并发编程中的三个概念: 1.原子性 在Java中,对基本数据类型的变量的读取和赋值操作是原子性操作,即这些操作是不可被中断的,要么执行,要么不执行. 2.可见性 对于可见性,Java提供了volati ...
随机推荐
- Linux(Ubuntu)与windows实现文件共享
步骤:1.从网上下载VMware和Ubuntu的镜像文件 2.在虚拟机上安装Ubuntu系统 3.在安装好的系统中安装VMware tools 实现文件共享 4.在VMware中设置与windo ...
- web安全学习神器——DVWA安装部署
前言 DVWA是用PHP+Mysql编写的一套用于常规WEB漏洞教学和检测的WEB脆弱性测试程序.包含了SQL注入.XSS.文件包含等常见的一些安全漏洞.接下来我会用图文的形式讲解一下DVWA的下载与 ...
- 一天学一个Linux命令:第一天 ls
文章更新于:2020-03-02 注:本文参照 man ls 手册,并给出使用样例. 文章目录 一.命令之`ls` 1.名字及介绍 2.语法格式 3.输出内容示例 4.参数 二.命令实践 1.`ls ...
- flask-redirect
flask-redirect from flask import Flask, url_for, request, redirect app = Flask(__name__) @app.route( ...
- django自定义实现登录验证-更新版
django自定义实现登录验证 django内置的登录验证必须让开发者使用django内置的User模块,这会让开发者再某些方面被限制住 下面的模块是我自己自定义实现的django验证,使用方式和dj ...
- Android视频悬浮窗口实现
前言 本文例子实现了点击显示悬浮窗口,同时窗口可播放视频,拖动位置,点击关闭及返回APP页面,通过例子来讲述悬浮窗口实现原理及细节处理,效果图如下所示: 原理 WindowManager对View视图 ...
- 个人项目 wc.exe
GitHub地址:https://github.com/oAiuo/wordCount 一.题目描述 Word Count1. 实现一个简单而完整的软件工具(源程序特征统计程序).2. 进行单元测试. ...
- CentOS Linux安装后扩充SWAP分区
1. 首先先查看目前swap分区大小: free -hm total used free shared buffers cached Mem: 11G 801M 10G 236K ...
- [leetcode]1379. Find a Corresponding Node of a Binary Tree in a Clone of That Tree
[leetcode]1379. Find a Corresponding Node of a Binary Tree in a Clone of That Tree 链接 leetcode 描述 ...
- Linux环境下django初入
python -m pip install --upgrade pip 终端中 一. 创建项目: 1.django-admin startproject mysite(第一种比较好) 2.django ...