`
Copperfield
  • 浏览: 254442 次
  • 性别: Icon_minigender_1
  • 来自: 上海
博客专栏
C407adc3-512e-3a03-a056-ce4607c3a3c0
java并发编程陷阱
浏览量:24592
社区版块
存档分类

并发编程陷阱系列(八)不要吞食CountDownLatch的线程异常

 
阅读更多

 之前的文章中已经介绍了无处不在的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/

 

 

分享到:
评论

相关推荐

    汪文君高并发编程实战视频资源下载.txt

    │ 高并发编程第一阶段32讲、如何捕获线程运行期间的异常.mp4 │ 高并发编程第一阶段33讲、ThreadGroup API介绍之一.mp4 │ 高并发编程第一阶段34讲、ThreadGroup API介绍之二.mp4 │ 高并发编程第一阶段35讲、...

    并发编程之CountDownLatch

    并发编程之CountDownLatch

    汪文君高并发编程实战视频资源全集

    │ 高并发编程第一阶段32讲、如何捕获线程运行期间的异常.mp4 │ 高并发编程第一阶段33讲、ThreadGroup API介绍之一.mp4 │ 高并发编程第一阶段34讲、ThreadGroup API介绍之二.mp4 │ 高并发编程第一阶段35讲、...

    java并发编程中CountDownLatch和CyclicBarrier的使用借鉴.pdf

    java并发编程中CountDownLatch和CyclicBarrier的使用借鉴.pdf

    java并发编程中CountDownLatch和CyclicBarrier的使用.pdf

    java并发编程中CountDownLatch和CyclicBarrier的使用.pdf

    并发编程示例,涉及到AtomicXXX、CountDownLatch、线程池等

    并发编程的一些小示例 1.等待通知的几种方式,包括Object的wait/notify,Condition的await/signal 2. CountDownLatch,统一控制多线程开始和结束 3.原子操作,AtomicXXX 4.线程池

    Java并发编程相关技术使用案例

    1、本资源包含并发编程基础知识的使用案例,包括:线程创建、Synchronized和Reentrantlock锁的使用、线程安全问题演示、Condition的应用、CountDownLatch的应用、Cyclicbarrier的应用、Semaphore的应用、线程池的...

    Java并发编程原理与实战

    线程的状态以及各状态之间的转换详解.mp4 线程的初始化,中断以及其源码讲解.mp4 多种创建线程的方式案例演示(一)带返回值的方式.mp4 多种创建线程的方式案例演示(二)使用线程池.mp4 Spring对并发的支持:Spring...

    Java并发编程一CountDownLatch、CyclicBarrier、Semaphore初使用

    Java并发编程一CountDownLatch、CyclicBarrier、Semaphore初使用 CountDownLatch、CyclicBarrier、Semaphore这些线程协作工具类是基于AQS的,看完这篇博客后可以去看下面这篇博客,了解它们是如何实现的。 Java并发...

    利用 CountDownLatch 类实现线程同步

    利用 CountDownLatch 类实现线程同步,而不用回调机制。详见我的博文 http://blog.csdn.net/kroclin/article/details/37956949

    Java 并发编程原理与实战视频

    java并发编程原理实战 第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四个...

    Java并发编程学习笔记

    7、并发工具类CountDownLatch 、CyclicBarrier和Semaphore底层实现原理 8、线程池原理和如何使用线程池 9、ThreadLocal 为什么会内存泄漏 10、Volatile底层实现原理 11、AQS源码分析 12、CAS原理分析和使用场景 13、...

    Java并发编程基础.pdf

    Java并发编程基础主要包括以下几个核心方面: ...并发工具类:掌握Java并发包java.util.concurrent中提供的各种工具类,如CountDownLatch、CyclicBarrier、Semaphore等,它们简化了并发编程的复杂性。

    并发编程面试专题.pdf

    1) 现在有 T1、T2、T3 三个线程,你怎样保证 T2 在 T1 执行完后执行,T3 在 T2 执行完后执行? 2) 在 Java 中 Lock 接口比 synchronized 块的优势是什么?你需要实现一个高效的缓存,它允许多个用户读,但只允许一个...

    Java并发编程实战

    书中从并发性和线程安全性的基本概念出发,介绍了如何使用类库提供的基本并发构建块,用于避免并发危险、构造线程安全的类及验证线程安全的规则,如何将小的线程安全类组合成更大的线程安全类,如何利用线程来提高...

    并发编程笔记20190526.docx

    第一章 线程基础、线程之间的共享和协作 3 一、基础概念 3 1. 什么是进程和线程 3 2. CPU核心数和线程数的关系 3 3. 澄清并行和并发 5 4. 多线程程序需要注意事项 6 二、认识Java里的线程 7 1. Java程序天生就是多...

    龙果 java并发编程原理实战

    龙果 java并发编程原理实战 第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四...

    mybaits 多线程 实现数据批量插入 (运用CountDownLatch实现闭锁)

    mybaits 多线程 实现数据批量插入 (运用CountDownLatch实现闭锁) 1、mybatis批处理 2、数据分批量查询 3、数据分批量插入

Global site tag (gtag.js) - Google Analytics