Explanation of java synchronization class CountDownLatch and javacountdownlatch
Synchronization helper class:
CountDownLatch is a synchronization helper class introduced in jdk5. it allows one or more threads to be executed after other threads have completed their operations.
Implementation principle:
CountDownLatch is implemented by counter. The initial value of the counter is the number of threads. Every time a thread completes its own task, it will subtract 1 from the counter. When the counter value is 0, it indicates that all threads have completed the task, at this time, the thread waiting for the lock will continue to execute, so as to continue the execution after other threads finish the task.
CountDownLatch methods:
CountDownLatch is implemented by means of a synchronization, And the AQS state is used to indicate the count:
/** * Synchronization control For CountDownLatch. * Uses AQS state to represent count. */ private static final class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = 4982264981922014374L; Sync(int count) { setState(count); } int getCount() { return getState(); } protected int tryAcquireShared(int acquires) { return (getState() == 0) ? 1 : -1; } protected boolean tryReleaseShared(int releases) { // Decrement count; signal when transition to zero for (;;) { int c = getState(); if (c == 0) return false; int nextc = c-1; if (compareAndSetState(c, nextc)) return nextc == 0; } } } private final Sync sync;
1. Constructor
public CountDownLatch(int count) { if (count < 0) throw new IllegalArgumentException("count < 0"); this.sync = new Sync(count); }
Create a CountDownLatch by passing in a value. The value indicates the number of times the thread can be restored from the waiting state. The countDown method must be called.
2. countDown Method
public void countDown() { sync.releaseShared(1); }
The thread calls this method to subtract 1 from count. When count is originally 0, this method does not perform any operation. When count is greater than 0, this method is called to reduce 1. When new count is 0, all waiting threads are released.
3. await Method
(1) Without Parameters
public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1); }
When this method is called, when count is 0, true is directly returned. When count is greater than 0, the thread will wait until the value of count changes to 0, or the thread is interrupted (interepted, in this case, an interrupt exception is thrown ).
(2) With Parameters
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout)); }
When this method is called, when count is 0, true is directly returned. When count is greater than 0, the thread will wait for a period of time. If the count value changes to 0 within the waiting period, true is returned; if the waiting time is exceeded, false is returned; or the thread is interrupted during the waiting time, an interruption exception is thrown.
CountDownLatch practices
Drivers and workers must wait until the driver arrives to load the car. The driver must wait until all workers have loaded the goods into the car before driving the car.
WORKER:
public class Worker implements Runnable { private String workerCode; private CountDownLatch startLatch; private CountDownLatch latch; Worker(CountDownLatch startLatch, CountDownLatch latch, String workerCode) { this.startLatch = startLatch; this.latch = latch; this.workerCode = workerCode; } public void run() { try { startLatch.await(); doWork(); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } private void doWork() { System.out.println("Worker " + workerCode + " is loading goods..."); }}
Drivers:
public class Driver { public static void main(String[] args) throws InterruptedException { CountDownLatch startLatch = new CountDownLatch(1); CountDownLatch latch = new CountDownLatch(10); ExecutorService executor = Executors.newFixedThreadPool(10); for(int i=0; i<10; i++) { executor.execute(new Worker(startLatch, latch, "worker" + i)); } System.out.println("Driver is here."); startLatch.countDown(); System.out.println("Workers get to work."); latch.await(); System.out.println("Driver is ready to go."); executor.shutdown(); }}
Running result:
Driver is here.Workers get to work.Worker worker0 is loading goods...Worker worker1 is loading goods...Worker worker2 is loading goods...Worker worker3 is loading goods...Worker worker4 is loading goods...Worker worker5 is loading goods...Worker worker7 is loading goods...Worker worker9 is loading goods...Worker worker8 is loading goods...Worker worker6 is loading goods...Driver is ready to go.
Complete project code see git: https://github.com/xuweijian/CountDownLatch.git