CountDownLatch应用及原理

    xiaoxiao2023-10-13  182

    正如每个Java文档所描述的那样,CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行。

    CountDownLatch是在java1.5被引入的,跟它一起被引入的并发工具类还有CyclicBarrier、Semaphore、ConcurrentHashMap和BlockingQueue,它们都存在于java.util.concurrent包下。CountDownLatch这个类能够使一个线程等待其他线程完成各自的工作后再执行。例如,应用程序的主线程希望在负责启动框架服务的线程已经启动所有的框架服务之后再执行。

    CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。

    CountDownLatch的方法

    //可中断等待 public void await() throws InterruptedException; //等待直到超时或者中断 public boolean await(long timeout, TimeUnit unit)throws InterruptedException; //计数器减1 public void countDown();

    CountDownLatch的应用

    控制线程同时执行

    package main.java.study;

    import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.CountDownLatch;

    public class CountDownLatchTest {

        public class MapOper implements Runnable {                  CountDownLatch latch ;

            public MapOper(CountDownLatch latch) {             this.latch = latch;         }

            public void run() {             try {                                   SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");                 System.out.println(Thread.currentThread().getName() + "start:" + df.format(new Date()));                                  latch.await();                 System.out.println(Thread.currentThread().getName() + "work:" + df.format(new Date()));                              } catch (InterruptedException e) {                 // TODO Auto-generated catch block                 e.printStackTrace();             }             System.out.println(Thread.currentThread().getName()+" Sync Started!");         }     }

             public static void main(String[] args) throws InterruptedException {         // TODO Auto-generated method stub         CountDownLatchTest test = new CountDownLatchTest();                  CountDownLatch latch = new CountDownLatch(1);                  Thread t1 = new Thread(test.new MapOper(latch));         Thread t2 = new Thread(test.new MapOper(latch));         Thread t3 = new Thread(test.new MapOper(latch));         Thread t4 = new Thread(test.new MapOper(latch));                  t1.setName("Thread1");         t2.setName("Thread2");         t3.setName("Thread3");         t4.setName("Thread4");                  t1.start();         Thread.sleep(1500);         t2.start();         Thread.sleep(1500);         t3.start();         Thread.sleep(1500);         t4.start();                           System.out.println("thread already start, sleep for a while...");                  Thread.sleep(1000);         latch.countDown();

        }          

    }

    执行结果:线程在不同时刻启动,但是等待后在同一时刻工作。

    Thread1start:2019-05-25 13:24:01 Thread2start:2019-05-25 13:24:02 Thread3start:2019-05-25 13:24:04 thread already start, sleep for a while... Thread4start:2019-05-25 13:24:05 Thread1work:2019-05-25 13:24:06 Thread1 Sync Started! Thread2work:2019-05-25 13:24:06 Thread2 Sync Started! Thread3work:2019-05-25 13:24:06 Thread3 Sync Started! Thread4work:2019-05-25 13:24:06 Thread4 Sync Started!

    CountDownLatch的原理

    调用countDownLatch.await()方法的线程,它会处于挂起状态,直到所有的线程都执行完countDownLatch.countDown方法,最终将计数器减为0,才会被唤醒继续执行。

    CountDownLatch的源码

    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) { //只有state为0时,才返回1,其他返回-1,小于0则 表示acquire失败。 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;//每次state减1 if (compareAndSetState(c, nextc)) return nextc == 0; } } } public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1); } //countDown,release(1) public void countDown() { sync.releaseShared(1); }

    AbstractQueuedSynchronizer相关源码参考:https://blog.csdn.net/demon7552003/article/details/90105335

    最新回复(0)