1. Background:
- countDownLatch was introduced in Java 1.5, along with CyclicBarrier, Semaphore, concurrentHashMap and BlockingQueue.
- Exists in java.util.cucurrent Under the bag.
2. Concept
- countDownLatch is a class that enables a thread to wait for other threads to complete their execution before executing.
- It is implemented by a counter whose initial value is the number of threads. Every time a thread finishes executing, the counter value is - 1. When the counter value is 0, it means that all threads have finished executing, and then the thread waiting on the lock can resume working.
3. Source code
- Only one constructor is provided in the countDownLatch class:
- //Parameter count is the count value
public CountDownLatch(int count) { };
- There are three methods that are most important in a class:
//call await()Method will be suspended and it will wait until count 0 to continue public void await() throws InterruptedException { }; //and await()Similar, just wait for a certain time count If the value hasn't changed to 0, it will continue to execute public boolean await(long timeout, TimeUnit unit) throws InterruptedException { }; //take count Value minus 1 public void countDown() { };
4. Examples
General example:
public class CountDownLatchTest { public static void main(String[] args) { final CountDownLatch latch = new CountDownLatch(2); System.out.println("Main thread start execution"); //First sub thread execution ExecutorService es1 = Executors.newSingleThreadExecutor(); es1.execute(new Runnable() { @Override public void run() { try { Thread.sleep(3000); System.out.println("Child thread:"+Thread.currentThread().getName()+"implement"); } catch (InterruptedException e) { e.printStackTrace(); } latch.countDown(); } }); es1.shutdown(); //Second sub thread execution ExecutorService es2 = Executors.newSingleThreadExecutor(); es2.execute(new Runnable() { @Override public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Child thread:"+Thread.currentThread().getName()+"implement"); latch.countDown(); } }); es2.shutdown(); System.out.println("Wait for two threads to finish"); try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Both sub threads are finished, continue to execute the main thread"); } }
Result set:
Main thread start execution Wait for two threads to finish Subthread: pool-1-thread-1 execution Subthread: pool-2-thread-1 execution Both sub threads are finished, continue to execute the main thread
Simulation concurrency example:
public class Parallellimit { public static void main(String[] args) { ExecutorService pool = Executors.newCachedThreadPool(); CountDownLatch cdl = new CountDownLatch(100); for (int i = 0; i < 100; i++) { CountRunnable runnable = new CountRunnable(cdl); pool.execute(runnable); } } } class CountRunnable implements Runnable { private CountDownLatch countDownLatch; public CountRunnable(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } @Override public void run() { try { synchronized (countDownLatch) { /*** One capacity reduction at a time*/ countDownLatch.countDown(); System.out.println("thread counts = " + (countDownLatch.getCount())); } countDownLatch.await(); System.out.println("concurrency counts = " + (100 - countDownLatch.getCount())); } catch (InterruptedException e) { e.printStackTrace(); } } }