GNU Classpath (0.98) | |
Frames | No Frames |
1: /* 2: * Written by Doug Lea with assistance from members of JCP JSR-166 3: * Expert Group and released to the public domain, as explained at 4: * http://creativecommons.org/licenses/publicdomain 5: */ 6: 7: package java.util.concurrent; 8: import java.util.concurrent.locks.*; 9: import java.util.concurrent.atomic.*; 10: 11: /** 12: * A synchronization aid that allows one or more threads to wait until 13: * a set of operations being performed in other threads completes. 14: * 15: * <p>A {@code CountDownLatch} is initialized with a given <em>count</em>. 16: * The {@link #await await} methods block until the current count reaches 17: * zero due to invocations of the {@link #countDown} method, after which 18: * all waiting threads are released and any subsequent invocations of 19: * {@link #await await} return immediately. This is a one-shot phenomenon 20: * -- the count cannot be reset. If you need a version that resets the 21: * count, consider using a {@link CyclicBarrier}. 22: * 23: * <p>A {@code CountDownLatch} is a versatile synchronization tool 24: * and can be used for a number of purposes. A 25: * {@code CountDownLatch} initialized with a count of one serves as a 26: * simple on/off latch, or gate: all threads invoking {@link #await await} 27: * wait at the gate until it is opened by a thread invoking {@link 28: * #countDown}. A {@code CountDownLatch} initialized to <em>N</em> 29: * can be used to make one thread wait until <em>N</em> threads have 30: * completed some action, or some action has been completed N times. 31: * 32: * <p>A useful property of a {@code CountDownLatch} is that it 33: * doesn't require that threads calling {@code countDown} wait for 34: * the count to reach zero before proceeding, it simply prevents any 35: * thread from proceeding past an {@link #await await} until all 36: * threads could pass. 37: * 38: * <p><b>Sample usage:</b> Here is a pair of classes in which a group 39: * of worker threads use two countdown latches: 40: * <ul> 41: * <li>The first is a start signal that prevents any worker from proceeding 42: * until the driver is ready for them to proceed; 43: * <li>The second is a completion signal that allows the driver to wait 44: * until all workers have completed. 45: * </ul> 46: * 47: * <pre> 48: * class Driver { // ... 49: * void main() throws InterruptedException { 50: * CountDownLatch startSignal = new CountDownLatch(1); 51: * CountDownLatch doneSignal = new CountDownLatch(N); 52: * 53: * for (int i = 0; i < N; ++i) // create and start threads 54: * new Thread(new Worker(startSignal, doneSignal)).start(); 55: * 56: * doSomethingElse(); // don't let run yet 57: * startSignal.countDown(); // let all threads proceed 58: * doSomethingElse(); 59: * doneSignal.await(); // wait for all to finish 60: * } 61: * } 62: * 63: * class Worker implements Runnable { 64: * private final CountDownLatch startSignal; 65: * private final CountDownLatch doneSignal; 66: * Worker(CountDownLatch startSignal, CountDownLatch doneSignal) { 67: * this.startSignal = startSignal; 68: * this.doneSignal = doneSignal; 69: * } 70: * public void run() { 71: * try { 72: * startSignal.await(); 73: * doWork(); 74: * doneSignal.countDown(); 75: * } catch (InterruptedException ex) {} // return; 76: * } 77: * 78: * void doWork() { ... } 79: * } 80: * 81: * </pre> 82: * 83: * <p>Another typical usage would be to divide a problem into N parts, 84: * describe each part with a Runnable that executes that portion and 85: * counts down on the latch, and queue all the Runnables to an 86: * Executor. When all sub-parts are complete, the coordinating thread 87: * will be able to pass through await. (When threads must repeatedly 88: * count down in this way, instead use a {@link CyclicBarrier}.) 89: * 90: * <pre> 91: * class Driver2 { // ... 92: * void main() throws InterruptedException { 93: * CountDownLatch doneSignal = new CountDownLatch(N); 94: * Executor e = ... 95: * 96: * for (int i = 0; i < N; ++i) // create and start threads 97: * e.execute(new WorkerRunnable(doneSignal, i)); 98: * 99: * doneSignal.await(); // wait for all to finish 100: * } 101: * } 102: * 103: * class WorkerRunnable implements Runnable { 104: * private final CountDownLatch doneSignal; 105: * private final int i; 106: * WorkerRunnable(CountDownLatch doneSignal, int i) { 107: * this.doneSignal = doneSignal; 108: * this.i = i; 109: * } 110: * public void run() { 111: * try { 112: * doWork(i); 113: * doneSignal.countDown(); 114: * } catch (InterruptedException ex) {} // return; 115: * } 116: * 117: * void doWork() { ... } 118: * } 119: * 120: * </pre> 121: * 122: * <p>Memory consistency effects: Actions in a thread prior to calling 123: * {@code countDown()} 124: * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a> 125: * actions following a successful return from a corresponding 126: * {@code await()} in another thread. 127: * 128: * @since 1.5 129: * @author Doug Lea 130: */ 131: public class CountDownLatch { 132: /** 133: * Synchronization control For CountDownLatch. 134: * Uses AQS state to represent count. 135: */ 136: private static final class Sync extends AbstractQueuedSynchronizer { 137: private static final long serialVersionUID = 4982264981922014374L; 138: 139: Sync(int count) { 140: setState(count); 141: } 142: 143: int getCount() { 144: return getState(); 145: } 146: 147: public int tryAcquireShared(int acquires) { 148: return getState() == 0? 1 : -1; 149: } 150: 151: public boolean tryReleaseShared(int releases) { 152: // Decrement count; signal when transition to zero 153: for (;;) { 154: int c = getState(); 155: if (c == 0) 156: return false; 157: int nextc = c-1; 158: if (compareAndSetState(c, nextc)) 159: return nextc == 0; 160: } 161: } 162: } 163: 164: private final Sync sync; 165: 166: /** 167: * Constructs a {@code CountDownLatch} initialized with the given count. 168: * 169: * @param count the number of times {@link #countDown} must be invoked 170: * before threads can pass through {@link #await} 171: * @throws IllegalArgumentException if {@code count} is negative 172: */ 173: public CountDownLatch(int count) { 174: if (count < 0) throw new IllegalArgumentException("count < 0"); 175: this.sync = new Sync(count); 176: } 177: 178: /** 179: * Causes the current thread to wait until the latch has counted down to 180: * zero, unless the thread is {@linkplain Thread#interrupt interrupted}. 181: * 182: * <p>If the current count is zero then this method returns immediately. 183: * 184: * <p>If the current count is greater than zero then the current 185: * thread becomes disabled for thread scheduling purposes and lies 186: * dormant until one of two things happen: 187: * <ul> 188: * <li>The count reaches zero due to invocations of the 189: * {@link #countDown} method; or 190: * <li>Some other thread {@linkplain Thread#interrupt interrupts} 191: * the current thread. 192: * </ul> 193: * 194: * <p>If the current thread: 195: * <ul> 196: * <li>has its interrupted status set on entry to this method; or 197: * <li>is {@linkplain Thread#interrupt interrupted} while waiting, 198: * </ul> 199: * then {@link InterruptedException} is thrown and the current thread's 200: * interrupted status is cleared. 201: * 202: * @throws InterruptedException if the current thread is interrupted 203: * while waiting 204: */ 205: public void await() throws InterruptedException { 206: sync.acquireSharedInterruptibly(1); 207: } 208: 209: /** 210: * Causes the current thread to wait until the latch has counted down to 211: * zero, unless the thread is {@linkplain Thread#interrupt interrupted}, 212: * or the specified waiting time elapses. 213: * 214: * <p>If the current count is zero then this method returns immediately 215: * with the value {@code true}. 216: * 217: * <p>If the current count is greater than zero then the current 218: * thread becomes disabled for thread scheduling purposes and lies 219: * dormant until one of three things happen: 220: * <ul> 221: * <li>The count reaches zero due to invocations of the 222: * {@link #countDown} method; or 223: * <li>Some other thread {@linkplain Thread#interrupt interrupts} 224: * the current thread; or 225: * <li>The specified waiting time elapses. 226: * </ul> 227: * 228: * <p>If the count reaches zero then the method returns with the 229: * value {@code true}. 230: * 231: * <p>If the current thread: 232: * <ul> 233: * <li>has its interrupted status set on entry to this method; or 234: * <li>is {@linkplain Thread#interrupt interrupted} while waiting, 235: * </ul> 236: * then {@link InterruptedException} is thrown and the current thread's 237: * interrupted status is cleared. 238: * 239: * <p>If the specified waiting time elapses then the value {@code false} 240: * is returned. If the time is less than or equal to zero, the method 241: * will not wait at all. 242: * 243: * @param timeout the maximum time to wait 244: * @param unit the time unit of the {@code timeout} argument 245: * @return {@code true} if the count reached zero and {@code false} 246: * if the waiting time elapsed before the count reached zero 247: * @throws InterruptedException if the current thread is interrupted 248: * while waiting 249: */ 250: public boolean await(long timeout, TimeUnit unit) 251: throws InterruptedException { 252: return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout)); 253: } 254: 255: /** 256: * Decrements the count of the latch, releasing all waiting threads if 257: * the count reaches zero. 258: * 259: * <p>If the current count is greater than zero then it is decremented. 260: * If the new count is zero then all waiting threads are re-enabled for 261: * thread scheduling purposes. 262: * 263: * <p>If the current count equals zero then nothing happens. 264: */ 265: public void countDown() { 266: sync.releaseShared(1); 267: } 268: 269: /** 270: * Returns the current count. 271: * 272: * <p>This method is typically used for debugging and testing purposes. 273: * 274: * @return the current count 275: */ 276: public long getCount() { 277: return sync.getCount(); 278: } 279: 280: /** 281: * Returns a string identifying this latch, as well as its state. 282: * The state, in brackets, includes the String {@code "Count ="} 283: * followed by the current count. 284: * 285: * @return a string identifying this latch, as well as its state 286: */ 287: public String toString() { 288: return super.toString() + "[Count = " + sync.getCount() + "]"; 289: } 290: }
GNU Classpath (0.98) |