J.U.C之AQS CountDownLatch

CountDownLatch概述

  • 阻塞当前线程功能;
  • 初始化的时候指定了计数器的值,多线程对计数器的值的操作是原子性的,同时只能有一个线程操作其中计数器的值;
  • 调用该类的await()方法的线程会一直处于阻塞状态,直到其他线程调用countDown(),将当前计数器的值减为0,每次调用countDown()的时候,计数器的值减1,当计数器的值减为0时,所有因调用await()方法而阻塞的线程都会继续执行;
  • 其中计数器的值是不能被重置的,如果是需要重置计数器的版本,可以考虑CyclicBarrier;

CountDownLatch使用场景

  • 程序需要等待某个条件完成后,才能继续执行,典型运用比如:并行计算,当某个处理的值很大时,可以将该运算任务拆成多个子任务,等到所有子任务运算完成后,父任务拿到所有子任务的运算结果进行汇总;

CountDownLatch示例(一)

  • CountDownLatch使用步骤
    • 初始化时指定计数器的值;
    • 前置线程中记得调用countDownLatch.countDown()方法;
    • 主线程(后置线程)要调用countDownLatch.await()等待前置线程运行完成;
  • 如果countDownLatch.countDown()是一定要执行的,可以放在finally中,以防程序抛出异常是可能执行;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Slf4j
public class CountDownLatchExample1 {

    private final static int threadCount = 200;

    public static void main(String[] args) throws Exception {

        ExecutorService exec = Executors.newCachedThreadPool();

        final CountDownLatch countDownLatch = new CountDownLatch(threadCount);

        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;
            exec.execute(() -> {
                try {
                    test(threadNum);
                } catch (Exception e) {
                    log.error("exception", e);
                } finally {
                    countDownLatch.countDown();
                }
            });
        }
        countDownLatch.await();
        log.info("finish");
        exec.shutdown();
    }

    private static void test(int threadNum) throws Exception {
        Thread.sleep(100);
        log.info("{}", threadNum);
        Thread.sleep(100);
    }
}

CountDownLatch示例(一)规定等待时间

  • countDownLatch.await(10, TimeUnit.MILLISECONDS)如果指定了等待时间,则主线程的执行不依赖于前置线程都执行完成,即不依赖于countDownLatch中的计数器减为0;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Slf4j
public class CountDownLatchExample2 {

    private final static int threadCount = 200;

    public static void main(String[] args) throws Exception {

        ExecutorService exec = Executors.newCachedThreadPool();

        final CountDownLatch countDownLatch = new CountDownLatch(threadCount);

        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;
            exec.execute(() -> {
                try {
                    test(threadNum);
                } catch (Exception e) {
                    log.error("exception", e);
                } finally {
                    countDownLatch.countDown();
                }
            });
        }
        countDownLatch.await(10, TimeUnit.MILLISECONDS);
        log.info("finish");
        exec.shutdown();
    }

    private static void test(int threadNum) throws Exception {
        Thread.sleep(100);
        log.info("{}", threadNum);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值