线程工具类 - CountDownLatch

CountDownLatch官方使用手册:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html

一、原理

  CountDownLatch是一个非常实用的多线程控制工具类。Count Down在英文中意为倒计时,Latch意为门闩,可以简单的将CountDownLatch称为倒计时器。门闩的含义是:把门锁起来,不让里面的线程跑出来。因此,这个工具通常用来控制线程等待,它可以让一个线程等待知道倒计时结束,再开始执行。

  CountDownLatch内部维护着一个count计数,只不过对这个计数器的操作都是原子操作,同时只能有一个线程去操作这个计数器。CountDownLatch通过构造函数传入一个初始计数值,调用者可以通过调用CounDownLatch对象的countDown()方法,来使计数减1;如果调用对象上的await()方法,那么调用者就会一直阻塞在这里,直到别人通过countDown方法,将计数减到0,才可以继续执行。

  CountDownLatch的一种典型应用场景是火箭发射。在火箭发射前,为了保证万无一失,往往要进行各项设备、仪器的检查。只有等所有的检查完毕后,引擎才能点火。这种场景就非常适合使用CountDownLatch。它可以使得点火线程等待所有检查线程全部完成后再执行。

二、API

主要方法

  • public CountDownLatch(int count);

    构造方法参数指定了计数的次数

  • public void countDown();

    当前线程调用此方法,则计数减一

  • public void await() throws InterruptedException

    调用此方法会一直阻塞当前线程,直到计时器的值为0

三、Demo

CountDownLatch的一种典型用法是:

a group of worker threads use two countdown latches(一组工作线程使用两个CountDownLatch)。

Sample usage: a group of worker threads use two countdown latches(一组工作线程使用两个CountDownLatch):

  • The first is a start signal that prevents any worker from proceeding until the driver is ready for them to proceed;
  • The second is a completion signal that allows the driver to wait until all workers have completed

下面以一个Demo来说明CountDownLatch的使用。

程序功能:模拟多线程下载,合并线程等到所有下载任务完成便开始合并。

/**
 * CountDownLatch的典型用法2
 * 代码功能:使用多个下载线程实现下载,等到所有任务完成后合并线程开始合并。
 *
 * @author lp
 *
 */
public class CountDownLatchDemo2 {

    public static void main(String[] args) throws InterruptedException {
        int N = 8;
        CountDownLatch startSignal = new CountDownLatch(1);//startSignal控制开始
        CountDownLatch doneSignal = new CountDownLatch(N);//

        ExecutorService executor = Executors.newFixedThreadPool(N + 1);// 8个下载线程,1个合并线程

        // let all threads proceed
        startSignal.countDown();

        // N个下载任务开始执行
        for (int i = 0; i < N; ++i) {
            executor.execute(new DownloadRunnable(startSignal,doneSignal, i));
        }

        // wait for all to finish
        doneSignal.await();//阻塞,直到计数器为0

        // 执行合并任务
        executor.execute(new MergeRunnable());

        executor.shutdown();
    }
}

/**
 * 下载线程
 */
class DownloadRunnable implements Runnable {
    private final CountDownLatch startSignal;
    private final CountDownLatch doneSignal;
    private final int i;

    public DownloadRunnable(CountDownLatch startSignal, CountDownLatch doneSignal, int i) {
        this.startSignal = startSignal;
        this.doneSignal = doneSignal;
        this.i = i;
    }

    public void run() {
        try {
            startSignal.await();//当前线程等待
            doDownload(i);
            doneSignal.countDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    private void doDownload(int i) {
        System.out.println("Thead:" + i + "下载完成");
    }
}

Another typical usage would be to divide a problem into N parts, describe each part with a Runnable that executes that portion and counts down on the latch, and queue all the Runnables to an Executor. When all sub-parts are complete, the coordinating thread will be able to pass through await. (When threads must repeatedly count down in this way, instead use a CyclicBarrier.)

另外一种典型的用法是:将一个问题分解成N部分,用Runnable来描述每一部分任务,每个Runnable执行完后将latch数减1,而且要将所有的Runnable都加入到Executor中。当所有子部分任务完成时,协调线程经过await后能够开始执行。(当线程必须可重复性的倒计时时,请使用CyclicBarrier代替)

/**
 * CountDownLatch的典型用法1
 * 代码功能:模拟多线程下载功能-使用多个下载线程实现下载,等到所有任务完成后合并线程开始合并。
 *
 * @author lp
 *
 */
public class CountDownLatchDemo {

    public static void main(String[] args) throws InterruptedException {
        int N = 8;
        CountDownLatch doneSignal = new CountDownLatch(N);// 计数器从N开始倒数
        ExecutorService executor = Executors.newFixedThreadPool(N + 1);// N个下载线程,1个合并线程

        // N个下载任务开始执行
        for (int i = 0; i < N; ++i) {
            executor.execute(new DownloadRunnable(doneSignal, i));
        }

        // wait for all to finish
        doneSignal.await();//阻塞,直到计数器为0

        // 执行合并任务
        executor.execute(new MergeRunnable());

        executor.shutdown();
    }
}

/**
 * 下载线程
 */
class DownloadRunnable implements Runnable {
    private final CountDownLatch doneSignal;
    private final int i;

    DownloadRunnable(CountDownLatch doneSignal, int i) {
        this.doneSignal = doneSignal;
        this.i = i;
    }

    public void run() {
        doDownload(i);
        doneSignal.countDown();
    }

    private void doDownload(int i) {
        System.out.println("Thead:" + i + "下载完成");
    }
}

/**
 * 合并线程
 */
class MergeRunnable implements Runnable{

    @Override
    public void run() {
        doMerge();
    }

    private void doMerge(){
        System.out.println("合并线程完成合并");
    }

}
时间: 2024-08-24 16:16:25

线程工具类 - CountDownLatch的相关文章

Java并发工具类 - CountDownLatch

Java并发工具类 - CountDownLatch 1.简介 CountDownLatch是Java1.5之后引入的Java并发工具类,放在java.util.concurrent包下面 http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html 官方API. CountDownLatch能够使一个或多个线程等待其他线程完成各自的工作后再执行:CountDownLatch是JDK 5+里面

同步工具类 CountDownLatch 和 CyclicBarrier

在开发中,一些异步操作会明显加快执行速度带来更好的体验,但同时也增加了开发的复杂度,想了用好多线程,就必须从这些方面去了解 线程的 wait() notify() notifyall() 方法 线程异步返回 Future ThreadLocal 类 线程池 ThreadPoolExecutor 同步工具类 CountDownLatch,CyclicBarrier,Semaphore,Phaser,Exchanger 估计上面每一个对于 2~3 年的 java 同学来说都是恶梦,比较难以理解,本文

java同步并发工具类CountDownLatch、CyclicBarrier和Semaphore

闭锁CountDownLatch 闭锁是一种同步工具类,可以延迟线程的进度直到其到达终止状态.闭锁的作用相当于一扇门:在闭锁到达结束状态之前,这扇门一直是关闭的,并且没有任何线程能通过,当到达结束状态时,这扇门会打开并允许所有的线程通过.当闭锁到达结束状态后,将不会再改变状态,因此这扇门将永远保持打开状态.闭锁可以用来确保某些活动直到其他活动都完成后才继续执行,例如: 确保某个计算在其需要的所有资源都被初始化之后才继续执行.二元闭锁(包括两个状态)可以用来表示"资源R已经被初始化",而

25.大白话说java并发工具类-CountDownLatch,CyclicBarrier,Semaphore,Exchanger

1. 倒计时器CountDownLatch 在多线程协作完成业务功能时,有时候需要等待其他多个线程完成任务之后,主线程才能继续往下执行业务功能,在这种的业务场景下,通常可以使用Thread类的join方法,让主线程等待被join的线程执行完之后,主线程才能继续往下执行.当然,使用线程间消息通信机制也可以完成.其实,java并发工具类中为我们提供了类似"倒计时"这样的工具类,可以十分方便的完成所说的这种业务场景. 为了能够理解CountDownLatch,举一个很通俗的例子,运动员进行跑

JUC常用同步工具类——CountDownLatch,CyclicBarrier,Semaphore

在 JUC 下包含了一些常用的同步工具类,今天就来详细介绍一下,CountDownLatch,CyclicBarrier,Semaphore 的使用方法以及它们之间的区别. 一.CountDownLatch 先看一下,CountDownLatch 源码的官方介绍. 意思是,它是一个同步辅助器,允许一个或多个线程一直等待,直到一组在其他线程执行的操作全部完成. public CountDownLatch(int count) { if (count < 0) throw new IllegalAr

Java多线程及JDK5线程工具类总结

内容摘抄来自:传智播客 张孝祥 老师的<Java高新技术>视频,   并加入了个人总结和理解. 虽然我没有参加过任何培训班,但我很大一部分知识都来自于传智播客的网络分享视频. 十分真挚的感谢张老师的公开视频. 1.传统线程技术的回顾 1 import org.junit.Test; 2 /** 3 * 传统线程回顾 4 * 多线程不一定会提高运行效率,和CPU设计和架构有关. 5 * 多线程下载是抢了服务器的资源,并不是自身的机器加快. 6 * @author LiTaiQing 7 */ 8

1.3.4 并发工具类CountDownLatch/Semaphore/CyclicBarrier/FutureTask

CountDownLatch的2个用途: 1. 所有线程都到达相同的起跑线后,再一起开始跑(并非同时开始,而是队列中一个唤醒另一个)[此情况需到达起跑线后再调用await()等待其他线程] 2. 所有线程都到达终点(执行完)后,再一起庆祝 (并非同时开始,而是队列中一个唤醒另一个)[此情况需到达起终点后再调用await()等待其他线程] package com.study.concurrent_utils; import java.util.concurrent.CountDownLatch;

线程工具类 - FutureTask

java中可以通过继承Thread或者实现Runnable接口来实现多线程,但是这种方式并不能让我们在线程执行完后获取执行结果.因此在java1.5开始引入了Callable和Future接口,通过它们可以在线程执行完后获取执行结果.Callable表示一个可返回结果的任务,Future表示一个异步计算的结果 一.Callable接口 public interface Callable<V> { /** * Computes a result, or throws an exception i

线程工具类ThreadUtils

package yqw.java.util; public class ThreadUtils { /**     * showThreadInfo     *      * @return     */    public static final String showThreadInfo() { return "^^^^^^^^^^^^^^^^^^^^^^^ currentThread: name=" + Thread.currentThread().getName() + &q