CountDownLatch介绍

java.util.concurrent.CountDownLatch

 

介绍:

    CountDownLatch是一个开闭锁,允许多个线程同时阻塞在一个点,然后通过信号量来同时释放线程。就好像赛马比赛:所有的马(Thread)都等着栅栏(Singal)放开那一刻,放开后,奋力前行,到达终点(CPU或者其他资源)。

    CountDownLatch初始化方法为:CountDownLatch(int count) ;需要给定一个计数器,这个计数器就是我们预期等待的线程个数。当调用CountDownLatch.await方法时,回去判断这个count是否为0,如果为0了则不会阻塞线程,如果不为0则阻塞。计数器count的值通过Co Latch.countDown()方法来减少。

    1、CountDownLatch可以做并发测试。

    比如:有一个服务UserService.addUser(String name)的流程为:先查询name是否存在,如果存在则返回false,否则返回true。这个接口需要确保当N个线程调用时,只有一个name可以插入。 

   

//这个例子在CountDownLatch的doc中,我只是将其改成具有业务含义的例子。 
 class Driver { 
   void main() throws InterruptedException {
     CountDownLatch startSignal = new CountDownLatch(1); //线程的栅栏,使所有现在都在某个点阻塞。
     CountDownLatch doneSignal = new CountDownLatch(N); //并发数

     for (int i = 0; i < N; ++i) // create and start threads
       new Thread(new Worker(startSignal, doneSignal)).start();

     doSomethingElse();            // do sth
     startSignal.countDown();      // let all threads proceed
     doSomethingElse();
     doneSignal.await();           // wait for all to finish
     assertOnlyOneUserName();      //所有线程都执行完成后,我们需要验证,只有一个Name存在。
   }
}

 //测试中,这个工作线程就是去调用addUser服务的。 class Worker implements Runnable {
   private final CountDownLatch startSignal;
   private final CountDownLatch doneSignal;
   Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
      this.startSignal = startSignal;
      this.doneSignal = doneSignal;
   }
   public void run() {
      try {
        startSignal.await();//所有线程必须等待主线程释放栅栏,释放后N个线程一起去抢占资源。
        doWork();
        doneSignal.countDown(); //N个线程全部完成后,唤醒主线程,让其验证N个线程调用服务后的结果。
      } catch (InterruptedException ex) {} // return;
   }

   void doWork() {
     UserService.addUser(xxx) ; //调用需要并发测试的服务

   }
 }
//以上只是一个简单的控制多个线程同时并发的例子。如果想做更精细的代码段测试,可以通过代码动/态编译技术,植入代码片段,让所有的线程都阻塞,然后通过某个信号量释放所有线程,达到并发目的。

 

    2、CountDownLatch另一个用法可能是多线程中做分片处理(分片任务的实现有很多,CountDownLatch只是一种)。

    

class Driver2 { // ...这个例子来自JDK的doc
   void main() throws InterruptedException {
     CountDownLatch doneSignal = new CountDownLatch(N);
     Executor e = ...

     for (int i = 0; i < N; ++i) // create and start threads
       e.execute(new WorkerRunnable(doneSignal, i));//这里其实是将资源分片,交给worker处理

     doneSignal.await();           // wait for all to finish
   }
 }

 class WorkerRunnable implements Runnable {
   private final CountDownLatch doneSignal;
   private final int i;
   WorkerRunnable(CountDownLatch doneSignal, int i) {
      this.doneSignal = doneSignal;
      this.i = i;
   }
   public void run() {
      try {
        doWork(i);
        doneSignal.countDown();
      } catch (InterruptedException ex) {} // return;
   }

   void doWork() { ... }
 }

 

 

 CountDownLatch是AQS共享锁的一个业务实现类。

 

        public int tryAcquireShared(int acquires) {
            return getState() == 0? 1 : -1;//这个方法主要是为了根据计数器来阻塞线程。
        }

        public boolean tryReleaseShared(int releases) { //如果计数器达到0则释放其他等待线程
            // 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;
            }
        }
 

 

public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

 public void countDown() {
        sync.releaseShared(1);
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中,CountDownLatch是一个同步工具类,用于控制多个线程的并发执行。它的主要作用是让一个或多个线程等待其他线程的完成。CountDownLatch的计数器初始值为正整数,每次调用countDown()方法会将计数器减1,计数器为0时,等待线程开始执行。 在Java中使用CountDownLatch的步骤如下: 1. 创建一个CountDownLatch对象,将计数器初始值设定为需要等待的线程数。 2. 在需要等待的线程中,调用countDown()方法,每次调用都会将计数器减1。 #### 引用[.reference_title] - *1* [JavaCountDownLatch用法解析](https://download.csdn.net/download/weixin_38543950/12788169)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [java并发之CountdownLatch](https://blog.csdn.net/qq_48508278/article/details/124265478)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [CountDownLatch介绍和使用【Java多线程必备】](https://blog.csdn.net/qq_45871274/article/details/130223673)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值