`

CountDownLatch

阅读更多

http://www.javamex.com/tutorials/threads/CountDownLatch.shtml

 

Coordinating threads with CountDownLatch

 

The CountDownLatch class allows us to coordinate the starting and stopping of threads. Typical uses are as follows:

  • we can make several threads start at the same time ;
  • we can wait for several threads to finish (whereas, for example, the Thread.join() method only lets you wait for a single thread).

Introduction to CountDownLatch

In concurrent programming, a latch is a type of "switch" or "trigger". The latch is set up with a particular count value. The count is then counted down , and at strategic moments, a thread or threads waits for the countdown to reach zero before continuing to perform some process. Note that this is a one-off process : once the latch reaches zero, there is no way to reset the count.

In Java:

  • the CountDownLatch object is constructed with the initial count;
  • calling countDown() decrements the count by 1;
  • the await() method will wait for the count to reach zero, or proceed immediately if the count already reached zero.

The CountDownLatch class is designed to be safe to call from multiple threads without any extra synchronization. (This differs, for example, from the wait/notify mechanism, where threads must be synchronized on the given lock object before calling wait() or notify() .)

Why use CountDownLatch (rather than wait/notify, Condition etc)?

The CountDownLatch protects you against the case of a thread missing a signal which can occur if you use these other mechanisms for coordinating jobs. Something like a Condition is useful for signalling to threads if they are waiting, but where it doesn't matter if they're not, or where a thread will explicitly check if it has to wait before waiting. With a CountDownLatch , we await a signal if it hasn't been triggered yet, but immediately continue without waiting if that signal was already triggered before we start waiting.

How to make several threads start at the same time

Sometimes it is useful to make a group of threads start at approximately the same time. For example, consider performance tests such as the ones conducted for this web site. If we're testing some throughput with n threads, it's only fair if the n threads start (and stop) at more or less the same time. In another situation, we might want a group of threads to start as soon as some asynchronous initialisation procedure is complete.

To coordinate the starting of several threads, we first create a CountDownLatch with an initial count of 1 . Then, each thread will sit at the start of its run() method, waiting for the latch to be counted down (i.e. sitting in the await() method). The thread performing the initialisation step (or just the thread coordinating the start of the other threads in the case of our performance experiment) then calls countDown() on the latch. Because the initial count was 1, this single countdown operation triggers all the other threads to start at (approximately) the same time.

If we define a subclass of Thread to handle the concurrent tasks, then we can arrange to pass the CountDownLatch into the constructor of those threads:

 

public class LatchedThread extends Thread {
  private final CountDownLatch startLatch;

  public LatchedThread(CountDownLatch startLatch) {
    this.startLatch = startLatch;
  }
  public void run() {
    try {
      startLatch.await();
      // ... perform task
    } catch (InterruptedException iex) {}
  }
}

 

Then, to coordinate the starting of 4 of these threads:

 

CountDownLatch startLatch = new CountDownLatch(10);
for (int threadNo = 0; threadNo < 4; threadNo++) {
  Thread t = new LatchedThread(startLatch);
  t.start();
}
// give the threads chance to start up; we could perform
// initialisation code here as well.
Thread.sleep(200);
startLatch.countDown();
 

When we call countDown() in the main thread, we don't actually know that all of the threads have started up; we just assume that sleeping for a fraction of a second gives them a "reasonable chance" of being ready for the signal. If any of the threads "misses the signal", it won't actually matter too much: when such a thread does start up, enter its run() method await() method, it will no longer actually wait, since the latch has already reached zero.

Bear in mind that inevitably, threads will "wake up" with approximate simultaneity : how simultaneous it can actually be depends on various factors, such as whether each thread can actually be allocated to a free processor, how "busy" the system is (what other threads are running and at what priorities), what threads are doing— i.e. how quickly running threads will relinquish the CPU— and what your particular operating system's policy is on prioritising waiting threads when they are signalled to wake up. (See the section on thread scheduling for more details about these factors.)

How to wait for several threads to complete

Another common scenario is with parallel processing , where we need to wait for several threads to finish or reach a particular point. In this case, we can use a similar mechanism:

  • we construct a CountDownLatch with the number of threads we want to wait for;
  • each thread counts down the latch on termination (or on finishing the job we're interested in).

This is therefore more flexible than the join() method, which only lets us wait for a single thread. Here is an example of waiting for 10 threads to complete:

 

public class StopLatchedThread extends Thread {
  private final CountDownLatch stopLatch;
  
  public StopLatchedThread(CountDownLatch stopLatch) {
    this.stopLatch = stopLatch;
  }
  public void run() {
    try {
      // perform interesting task
    } finally {
      stopLatch.countDown();
    }
  }
}

public void performParallelTask() throws InterruptedException {
  CountDownLatch cdl = new CountDownLatch(10);
  for (int i = 0; i < 10; i++) {
    Thread t = new StopLatchedThread(cdl);
    t.start();
  }
  cdl.await();
}
 

Interruptions and timeouts

A thread sitting in the await() method can be interrupted (generally by another thread calling interrupt() on it). Therefore, the await() method throws InterruptedException . Inside a run() method, the most appropriate action is usually to catch the exception around the whole logic of the method, so that interrupting the thread makes it exit. Where we are waiting for threads to complete inside a method, we can just make that method throw the exception up, and let the caller worry about what happens if the process is interrupted. For more information, see the section on thread interruption .

A version of the await() method takes a timeout (and TimeUnit in which the timeout is specified). Setting a timeout could be useful if, for example, the condition that a thread is awaiting is the initialisation of a driver, and there's a chance that the driver will not get initialised in a reasonably amount of time. In the timed case, the method returns true if the latch was actually triggered, and false if a timeout occurred. The timed method can still be interrupted and throw InterruptedException .

Coordinating multi-stage/iterated parallel processes

The CountDownLatch is useful for coordination of one-off operations. In the next section, we look at the CyclicBarrier class, which allows repeated or multi-stage parallel processes to be coordinated.

 

 

 

 

 

 

 

分享到:
评论

相关推荐

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

    本文将详细介绍如何利用MyBatis结合多线程和CountDownLatch闭锁来实现数据的批量插入。 首先,我们来看`mybatis批处理`。MyBatis的批处理功能允许我们在一次数据库连接中执行多条SQL语句,从而减少了数据库连接的...

    多线程countDownLatch方法介绍

    在Java多线程编程中,CountDownLatch是一个非常重要的同步工具类,它可以帮助我们协调多个线程之间的交互。本文将深入探讨CountDownLatch的工作原理、使用场景以及相关源码分析。 CountDownLatch是一个计数器,初始...

    利用 CountDownLatch 类实现线程同步

    Java 提供了多种工具来实现这样的同步机制,其中之一便是 `CountDownLatch` 类。`CountDownLatch` 是一个计数器,可以用于协调多个线程间的活动,等待所有线程完成各自的任务后,主线程或其他线程才能继续执行。 ...

    CountDownLatch和CyclicBarrier用法实例大全

    在Java并发编程中,CountDownLatch和CyclicBarrier是两种非常重要的同步工具类,它们用于协调多个线程间的协作。这两个工具都是在`java.util.concurrent`包下,是Java并发库的重要组成部分。 **CountDownLatch** ...

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

    java并发编程中CountDownLatch和CyclicBarrier的使用借鉴 java并发编程中CountDownLatch和CyclicBarrier是两个非常重要的线程控制和调度工具,经常被用于解决多线程程序设计中的线程等待问题。本文将对...

    CountDownLatch学习用法

    CountDownLatch是Java并发编程中一个重要的工具类,它属于java.util.concurrent包下的一个同步辅助类。这个类的设计目的是允许一个线程等待其他多个线程完成操作,然后再继续执行。CountDownLatch通常用于多线程协作...

    CountDownLatch练习

    CountDownLatch是Java并发编程中一个重要的同步工具类,它允许一个或多个线程等待其他线程完成操作。这个工具在多线程环境下的并行处理和协调中扮演着关键角色。 **CountDownLatch是什么?** CountDownLatch是一个...

    CountDownLatch与thread.join()的区别

    CountDownLatch与thread.join()的区别

    Java中的CountDownLatch与CyclicBarrier:深入理解与应用实践

    在Java的并发编程中,CountDownLatch和CyclicBarrier是两个非常重要的同步工具,它们用于协调多个线程的执行顺序。本文将详细介绍CountDownLatch和CyclicBarrier的工作原理、使用场景以及如何在实际项目中应用它们。...

    并发编程之CountDownLatch

    CountDownLatch 并发编程 CountDownLatch 是一个同步的辅助类,它可以允许一个或多个线程等待,直到一组在其它线程中的操作执行完成。它通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了...

    Java concurrency之CountDownLatch原理和示例_动力节点Java学院整理

    CountDownLatch是Java并发编程中一个重要的工具类,用于协调多线程间的同步。它由Java并发包`java.util.concurrent`提供,主要用于解决一种场景:在主控线程等待多个子线程完成各自任务后再继续执行的情况。下面我们...

    CountDownLatch详解.docx

    CountDownLatch 是 Java 中的一个同步工具类,位于 `java.util.concurrent` 包下,它主要用于多线程间的协作,尤其在需要等待所有线程执行完指定任务后才能继续执行的情况。这个类通过一个计数器(计数down)来实现...

    CountDownLatch的使用

    递减锁存器CountDownLatch的使用以及注意事项!

    countdownlatch-example-sourcecode.zip

    《CountDownLatch实战解析与源码探索》 CountDownLatch是Java并发编程中一个非常重要的同步工具类,它在多线程协作场景中起到了关键的作用。在`countdownlatch-example-sourcecode.zip`这个压缩包中,我们可以看到...

    27 倒数计时开始,三、二、一—CountDownLatch详解.pdf

    CountDownLatch 是 Java 中一个强大的并发工具类,常用于线程间的协调与同步。它由 Java Concurrency Utilities (JCU) 包中的 `java.util.concurrent` 类库提供。CountDownLatch 的核心功能是允许一个或多个线程等待...

    Java并发包之CountDownLatch用法.docx

    `CountDownLatch`是Java并发包`java.util.concurrent`中的一个重要工具类,用于实现线程间的同步。它基于计数器的概念,初始化时设置一个非负的计数值,然后通过调用`countDown()`方法来递减这个计数器。主线程或...

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

    在Java并发编程中,CountDownLatch和CyclicBarrier是两种非常重要的同步工具,用于协调多个线程之间的交互。它们都属于java.util.concurrent包下的类,为多线程编程提供了强大的支持。 **CountDownLatch** 是一个...

    CountDownLatch、Semaphore等4大并发工具类详解

    本文将详细介绍 Java 并发工具类的四大类:CountDownLatch、Semaphore、CyclicBarrier 和 Phaser,及其应用场景和使用方法。 CountDownLatch CountDownLatch 是一个同步的辅助类,允许一个或多个线程,等待其他一...

    CountDownLatch 和 CyclicBarrier 的运用(含AQS详解)

    ### CountDownLatch 和 CyclicBarrier 的运用(含AQS详解) #### CountDownLatch **定义与特点:** CountDownLatch 是 Java 并发包中的一个重要组件,它主要用于解决“一个或多个线程等待其他线程完成任务”的问题。...

    并发编程之Tools&CountDownLatch&Semaphore原理与应用1

    在这个场景中,我们主要讨论两种工具:Semaphore(信号量)和CountDownLatch。它们都是Java并发包(java.util.concurrent)中的工具类,用于协调多个线程之间的协作。 Semaphore,顾名思义,是一个信号量,它用于...

Global site tag (gtag.js) - Google Analytics