ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/CountDownLatch.java
Revision: 1.3
Committed: Sat Jun 7 18:20:20 2003 UTC (21 years ago) by dl
Branch: MAIN
CVS Tags: JSR166_PRELIMINARY_TEST_RELEASE_1
Changes since 1.2: +13 -11 lines
Log Message:
Misc documentation updates

File Contents

# Content
1 /*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain. Use, modify, and
4 * redistribute this code in any way without acknowledgement.
5 */
6
7 package java.util.concurrent;
8
9 /**
10 * A synchronization aid that allows a set of threads to wait until
11 * the actions of another set of threads allow the first set to
12 * proceed.
13 *
14 * <p>A <tt>CountDownLatch</tt> is initialized with a given
15 * <em>count</em>. The {@link #await} methods block until the current
16 * {@link #getCount count} reaches zero due to invocations of the
17 * {@link #countDown} method, after which all waiting threads are
18 * released and any subsequent invocations of {@link #await} return
19 * immediately. This is a one-shot phenomenon -- the count cannot be
20 * reset. If you need a version that resets the count, consider using
21 * a {@link CyclicBarrier}.
22 *
23 * <p>A <tt>CountDownLatch</tt> is a versatile synchronization tool
24 * and can be used for a number of purposes.
25 * A <tt>CountDownLatch</tt> initialized to one serves as a simple on/off
26 * latch, or gate: all threads invoking {@link #await} wait at the gate until
27 * it is opened by a thread invoking {@link #countDown}.
28 * A <tt>CountDownLatch</tt> initialized to <em>N</em> can be used to make
29 * one thread wait until <em>N</em> threads have completed some action.
30 * A useful property of a <tt>CountDownLatch</tt> is that it doesn't
31 * require that all threads wait before any can proceed, it simply
32 * prevents any thread from proceeding past the {@link #await wait} until
33 * all threads could pass.
34 *
35 * <p><b>Sample usage:</b> Here is a pair of classes in which a group
36 * of worker threads use two countdown latches:
37 * <ul>
38 * <li> The first is a start signal that prevents any worker from proceeding
39 * until the driver is ready for them to proceed;
40 * <li> The second is a completion signal that allows the driver to wait
41 * until all workers have completed.
42 * </ul>
43 *
44 * <pre>
45 * class Driver { // ...
46 * void main() throws InterruptedException {
47 * CountDownLatch startSignal = new CountDownLatch(1);
48 * CountDownLatch doneSignal = new CountDownLatch(N);
49 *
50 * for (int i = 0; i < N; ++i) // create and start threads
51 * new Thread(new Worker(startSignal, doneSignal)).start();
52 *
53 * doSomethingElse(); // don't let run yet
54 * startSignal.countDown(); // let all threads proceed
55 * doSomethingElse();
56 * doneSignal.await(); // wait for all to finish
57 * }
58 * }
59 *
60 * class Worker implements Runnable {
61 * private final CountDownLatch startSignal;
62 * private final CountDownLatch doneSignal;
63 * Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
64 * this.startSignal = startSignal;
65 * this.doneSignal = doneSignal;
66 * }
67 * public void run() {
68 * try {
69 * startSignal.await();
70 * doWork();
71 * doneSignal.countDown();
72 * }
73 * catch (InterruptedException ex) {} // return;
74 * }
75 *
76 * void doWork() { ... }
77 * }
78 *
79 * </pre>
80 *
81 * @since 1.5
82 * @spec JSR-166
83 * @revised $Date: 2003/05/27 18:14:39 $
84 * @editor $Author: dl $
85 */
86 public class CountDownLatch {
87 private final ReentrantLock lock = new ReentrantLock();
88 private final Condition zero = lock.newCondition();
89 private int count;
90
91 /**
92 * Constructs a <tt>CountDownLatch</tt> initialized with the given
93 * count.
94 *
95 * @param count the number of times {@link #countDown} must be invoked
96 * before threads can pass through {@link #await}.
97 *
98 * @throws IllegalArgumentException if <tt>count</tt> is less than zero.
99 */
100 public CountDownLatch(int count) {
101 if (count < 0) throw new IllegalArgumentException("count < 0");
102 this.count = count;
103 }
104
105 /**
106 * Causes the current thread to wait until the latch has counted down to
107 * zero, unless the thread is {@link Thread#interrupt interrupted}.
108 *
109 * <p>If the current {@link #getCount count} is zero then this method
110 * returns immediately.
111 * <p>If the current {@link #getCount count} is greater than zero then
112 * the current thread becomes disabled for thread scheduling
113 * purposes and lies dormant until one of two things happen:
114 * <ul>
115 * <li> The count reaches zero due to invocations of the
116 * {@link #countDown} method; or
117 * <li> Some other thread {@link Thread#interrupt interrupts} the current
118 * thread.
119 * </ul>
120 * <p>If the current thread:
121 * <ul>
122 * <li>has its interrupted status set on entry to this method; or
123 * <li>is {@link Thread#interrupt interrupted} while waiting,
124 * </ul>
125 * then {@link InterruptedException} is thrown and the current thread's
126 * interrupted status is cleared.
127 *
128 * @throws InterruptedException if the current thread is interrupted
129 * while waiting.
130 */
131 public void await() throws InterruptedException {
132 lock.lock();
133 try {
134 while (count != 0)
135 zero.await();
136 }
137 finally {
138 lock.unlock();
139 }
140 }
141
142
143 /**
144 * Causes the current thread to wait until the latch has counted down to
145 * zero, unless the thread is {@link Thread#interrupt interrupted},
146 * or the specified waiting time elapses.
147 *
148 * <p>If the current {@link #getCount count} is zero then this method
149 * returns immediately with the value <tt>true</tt>.
150 *
151 * <p>If the current {@link #getCount count} is greater than zero then
152 * the current thread becomes disabled for thread scheduling
153 * purposes and lies dormant until one of three things happen:
154 * <ul>
155 * <li>The count reaches zero due to invocations of the
156 * {@link #countDown} method; or
157 * <li>Some other thread {@link Thread#interrupt interrupts} the current
158 * thread; or
159 * <li>The specified waiting time elapses.
160 * </ul>
161 * <p>If the count reaches zero then the method returns with the
162 * value <tt>true</tt>.
163 * <p>If the current thread:
164 * <ul>
165 * <li>has its interrupted status set on entry to this method; or
166 * <li>is {@link Thread#interrupt interrupted} while waiting,
167 * </ul>
168 * then {@link InterruptedException} is thrown and the current thread's
169 * interrupted status is cleared.
170 *
171 * <p>If the specified waiting time elapses then the value <tt>false</tt>
172 * is returned.
173 * The given waiting time is a best-effort lower bound. If the time is
174 * less than or equal to zero, the method will not wait at all.
175 *
176 * @param timeout the maximum time to wait
177 * @param unit the time unit of the <tt>timeout</tt> argument.
178 * @return <tt>true</tt> if the count reached zero and <tt>false</tt>
179 * if the waiting time elapsed before the count reached zero.
180 *
181 * @throws InterruptedException if the current thread is interrupted
182 * while waiting.
183 */
184 public boolean await(long timeout, TimeUnit unit)
185 throws InterruptedException {
186 long nanos = unit.toNanos(timeout);
187 lock.lock();
188 try {
189 for (;;) {
190 if (count == 0)
191 return true;
192 nanos = zero.awaitNanos(nanos);
193 if (nanos <= 0)
194 return false;
195 }
196 }
197 finally {
198 lock.unlock();
199 }
200 }
201
202
203
204 /**
205 * Decrements the count of the latch, releasing all waiting threads if
206 * the count reaches zero.
207 * <p>If the current {@link #getCount count} is greater than zero then
208 * it is decremented. If the new count is zero then all waiting threads
209 * are re-enabled for thread scheduling purposes.
210 * <p>If the current {@link #getCount count} equals zero then nothing
211 * happens.
212 */
213 public void countDown() {
214 lock.lock();
215 try {
216 if (count > 0 && --count == 0)
217 zero.signalAll();
218 }
219 finally {
220 lock.unlock();
221 }
222 }
223
224 /**
225 * Returns the current count.
226 * <p>This method is typically used for debugging and testing purposes.
227 * @return the current count.
228 */
229 public long getCount() {
230 lock.lock();
231 try {
232 return count;
233 }
234 finally {
235 lock.unlock();
236 }
237 }
238 }