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实现闭锁) 1、mybatis批处理 2、数据分批量查询 3、数据分批量插入
《java并发编程》中CountDownLatch和CyclicBarrier用法实例大全,几乎包含了所有重要的用法
利用 CountDownLatch 类实现线程同步,而不用回调机制。详见我的博文 http://blog.csdn.net/kroclin/article/details/37956949
CountDownLatch与thread.join()的区别
java并发编程中CountDownLatch和CyclicBarrier的使用借鉴.pdf
递减锁存器CountDownLatch的使用以及注意事项!
目录 CountDownLatch是什么? CountDownLatch如何工作? 在实时系统中的应用场景 应用范例 常见的面试题 代码样例
在网上找的一个CountDownLatch的学习demo,感觉很不错,就摘抄过来了
NULL 博文链接:https://cpjsjxy.iteye.com/blog/2272451
并发编程之CountDownLatch
1.2 CountDownLatch概述 CountDownLatch的基本用法 2.1 创建CountDownLatch对象 2.2 await()方法 2.3 countDown()方法 实现多线程任务的同步 3.1 场景介绍 3.2 使用CountDownLatch实现同步 主线程等待多个线程完成 ...
Java并发编程一CountDownLatch、CyclicBarrier、Semaphore初使用 CountDownLatch、CyclicBarrier、Semaphore这些线程协作工具类是基于AQS的,看完这篇博客后可以去看下面这篇博客,了解它们是如何实现的。 Java并发...
其实我自认为CountDownLatch类是进入AQS世界一个非常好非常好的通道,因此写完这篇文章,我打算再写一篇关于CountDownLatch源码的文章。 1 原理简介 CountDownLatch原理可以用下图进行表示: 这里注意一下: 每个...
CountDownLatch是一个同步工具类,它通过一个计数器来实现的,初始值为线程的数量。每当一个线程完成了自己的任务,计数器的值就相应得减1。当计数器到达0时,表示所有的线程都已执行完毕,然后在等待的线程就可以恢复...
java并发工具类(CountDownLatch+Semaphore+Exchanger);java并发工具类(CountDownLatch+Semaphore+Exchanger);java并发工具类(CountDownLatch+Semaphore+Exchanger);java并发工具类(CountDownLatch+...
6.3 Semaphorer&CountDownLatch详 解副本.mp4
6.3 Semaphorer&CountDownLatch详 解副本副本.mp4
countdownlatch-example-sourcecode.zip
6.3 Semaphorer&CountDownLatch详 解副本副本副本.mp4
CountDownLatch、Semaphore等4大并发工具类详解,并介绍了简单的适用场景。