之前的文章中已经介绍了无处不在的InterruptedException的处理方式了,使用CountDownLatch也会有类似的问题(正确的处理方式见下面代码: Thread.currentThread().interrupt()),顺便复习下CountDownLatch的使用方法。
在一些应用中,有多个线程,某个线程会在其他线程执行完毕之后才开始执行。
比如,想象有一个程序先下载一堆网页,压缩然后通过EMAIL发送出去。如果要用多线程来实现,压缩网页的程序不能在下载完成后启动。
如何处理呢?一个非常简便的方法就是使用java.util.concurrent中的CountDownLatch。
在CountDownLatch中,你可以定义一个数字,每次操作完成后数字都会减一。如果所有操作都完成了,这个数字变成0,使用同一个CountDownLatch作为同步工具的其他线程可以调用await方法完成任务。
然我们看一个简单的例子,第一个类是一个简单的Runnable。在我们的例子中,这个类没什么用处,只是采取随机休眠的方式模拟一些任务的执行。
import java.util.Random; import java.util.concurrent.CountDownLatch; public class Worker implements Runnable { private CountDownLatch countDownLatch; public Worker(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } @Override public void run() { try { Thread.sleep(getRandomSeconds()); // sleep random time to simulate long running task System.out.println("Counting down: " + Thread.currentThread().getName()); this.countDownLatch.countDown(); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } } // returns a long between 0 and 9999 private long getRandomSeconds() { Random generator = new Random(); return Math.abs(generator.nextLong() % 10000); } }
唯一有意思的是这一行调用:
this.countDownLatch.countDown();
一旦任务执行完毕,countDownLatch中的计数器就会减一。
import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class WorkManager { private CountDownLatch countDownLatch; private static final int NUMBER_OF_TASKS = 5; public WorkManager() { countDownLatch = new CountDownLatch(NUMBER_OF_TASKS); } public void finishWork() { try { System.out.println("START WAITING"); countDownLatch.await(); System.out.println("DONE WAITING"); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } } public void startWork() { ExecutorService executorService = Executors.newFixedThreadPool(NUMBER_OF_TASKS); for (int i = 0; i < NUMBER_OF_TASKS; i++) { Worker worker = new Worker(countDownLatch); executorService.execute(worker); } executorService.shutdown(); } public static void main(String[] args) { WorkManager workManager = new WorkManager(); System.out.println("START WORK"); workManager.startWork(); System.out.println("WORK STARTED"); workManager.finishWork(); System.out.println("FINISHED WORK"); } }
startWork方法使用ExecutorService执行Runnable类。
在finishWork方法中,await方法会一直等待,直到CountDownLatch内部的计数器为0时,await后的方法才会继续执行下去。
执行结果:
START WORK WORK STARTED START WAITING Counting down: pool-1-thread-3 Counting down: pool-1-thread-4 Counting down: pool-1-thread-1 Counting down: pool-1-thread-5 Counting down: pool-1-thread-2 DONE WAITING FINISHED WORK
参考:http://markusjais.com/how-to-use-java-util-concurrent-countdownlatch/
相关推荐
│ 高并发编程第一阶段32讲、如何捕获线程运行期间的异常.mp4 │ 高并发编程第一阶段33讲、ThreadGroup API介绍之一.mp4 │ 高并发编程第一阶段34讲、ThreadGroup API介绍之二.mp4 │ 高并发编程第一阶段35讲、...
并发编程之CountDownLatch
│ 高并发编程第一阶段32讲、如何捕获线程运行期间的异常.mp4 │ 高并发编程第一阶段33讲、ThreadGroup API介绍之一.mp4 │ 高并发编程第一阶段34讲、ThreadGroup API介绍之二.mp4 │ 高并发编程第一阶段35讲、...
java并发编程中CountDownLatch和CyclicBarrier的使用借鉴.pdf
java并发编程中CountDownLatch和CyclicBarrier的使用.pdf
并发编程的一些小示例 1.等待通知的几种方式,包括Object的wait/notify,Condition的await/signal 2. CountDownLatch,统一控制多线程开始和结束 3.原子操作,AtomicXXX 4.线程池
1、本资源包含并发编程基础知识的使用案例,包括:线程创建、Synchronized和Reentrantlock锁的使用、线程安全问题演示、Condition的应用、CountDownLatch的应用、Cyclicbarrier的应用、Semaphore的应用、线程池的...
线程的状态以及各状态之间的转换详解.mp4 线程的初始化,中断以及其源码讲解.mp4 多种创建线程的方式案例演示(一)带返回值的方式.mp4 多种创建线程的方式案例演示(二)使用线程池.mp4 Spring对并发的支持:Spring...
Java并发编程一CountDownLatch、CyclicBarrier、Semaphore初使用 CountDownLatch、CyclicBarrier、Semaphore这些线程协作工具类是基于AQS的,看完这篇博客后可以去看下面这篇博客,了解它们是如何实现的。 Java并发...
利用 CountDownLatch 类实现线程同步,而不用回调机制。详见我的博文 http://blog.csdn.net/kroclin/article/details/37956949
java并发编程原理实战 第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四个...
7、并发工具类CountDownLatch 、CyclicBarrier和Semaphore底层实现原理 8、线程池原理和如何使用线程池 9、ThreadLocal 为什么会内存泄漏 10、Volatile底层实现原理 11、AQS源码分析 12、CAS原理分析和使用场景 13、...
Java并发编程基础主要包括以下几个核心方面: ...并发工具类:掌握Java并发包java.util.concurrent中提供的各种工具类,如CountDownLatch、CyclicBarrier、Semaphore等,它们简化了并发编程的复杂性。
1) 现在有 T1、T2、T3 三个线程,你怎样保证 T2 在 T1 执行完后执行,T3 在 T2 执行完后执行? 2) 在 Java 中 Lock 接口比 synchronized 块的优势是什么?你需要实现一个高效的缓存,它允许多个用户读,但只允许一个...
书中从并发性和线程安全性的基本概念出发,介绍了如何使用类库提供的基本并发构建块,用于避免并发危险、构造线程安全的类及验证线程安全的规则,如何将小的线程安全类组合成更大的线程安全类,如何利用线程来提高...
第一章 线程基础、线程之间的共享和协作 3 一、基础概念 3 1. 什么是进程和线程 3 2. CPU核心数和线程数的关系 3 3. 澄清并行和并发 5 4. 多线程程序需要注意事项 6 二、认识Java里的线程 7 1. Java程序天生就是多...
龙果 java并发编程原理实战 第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四...
mybaits 多线程 实现数据批量插入 (运用CountDownLatch实现闭锁) 1、mybatis批处理 2、数据分批量查询 3、数据分批量插入