搬砖日记-CountDownLatch和CompletableFuture的使用

15 篇文章 0 订阅

搬砖日记-CountDownLatch和CompletableFuture的使用

前言

不知不觉在大厂搬砖快一年了,在这一年里不得不说我学到了很多,特别把之前学到的知识给落地,这给我带来一些满足感和充实感,于是我想着抽空把最近学到的知识给整理整理,既是温习回顾还是一种分享,本篇文章将带领大家了解一下CountDownLatchCompletableFuture的使用.

正文

CountDownLatch

CountDownLatch程序计数器:

  • CountDownLatch用于主线程等待其他子线程任务都执行完毕后再执行.
  • CountDownLatch是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了.
  • 使用的场景:如多模块数据加速加载、治理大批量数据下游接口超时等

CountDownLatch主要的方法有:

  • await() :调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
  • await(long timeout,TimeUnit unit):只不过等待一定的时间后count值还没变为0的话就会继续执行(适用允许丢失部分数据的场景)
  • countDown():将count值减1

事例demo

import com.google.common.collect.Lists;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class Test020 {

    /**
     * 线程池
     */
    private static final ExecutorService QUERY_POOL = new ThreadPoolExecutor(
            10, 10,
            60, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(10000),
            new ThreadPoolExecutor.DiscardPolicy());

    public static void main(String[] args) {

        long start = System.currentTimeMillis();
        try {
            List<Long> resultList = new ArrayList<>();
            CountDownLatch countDownLatch = new CountDownLatch(4);
            for (int i = 0; i < 4; i++) {
                QUERY_POOL.execute(() -> {
                    try {
                        resultList.addAll(dohandler());
                    } finally {
                        countDownLatch.countDown();
                    }
                });
            }
            countDownLatch.await();
            System.out.println("结果:" + resultList + "耗时:" + (System.currentTimeMillis() - start));
        } catch (Exception e) {
            System.out.println("发生异常");
        }
    }

    public static List<Long> dohandler() {
        try {
            Thread.sleep(2500);
            return Lists.newArrayList(123L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }
}

运行结果:
在这里插入图片描述

CompletableFuture

CompletableFuture

  • CompletableFuture是对Future模式的应用即实现,支持流调用、异步执行,它支持完成后得到通知。
  • CompletableFuture默认的时候会使用ForkJoinPool池来执提供线程来执行任务.

ForkJoinPool 线程池在 JDK 8 加入,主要用法和之前的线程池是相同的,也是把任务交给线程池去执行,线程池中也有任务队列来存放任务,和之前的五种线程池不同的是,它非常适合执行可以分解子任务的任务,比如树的遍历,归并排序,或者其他一些递归场景。

在这里插入图片描述

CompletableFuture提供了四个静态方法用来创建对象:

  1. runAsync(Runnable runnable) :同步执行,使用默认线程池
  2. runAsync(Runnable runnable, Executor executor) :同步执行,手动线程池
  3. supplyAsync(Supplier supplier) :异步执行,使用默认线程池
  4. supplyAsync(Supplier supplier, Executor executor):异步执行,手动线程池

事例demo

  • CompletableFuture.get()会阻塞线程,所以get操作不要在任务分发循环体内进行,否则整个操作就不是多线程异步操作了.

    import com.google.common.collect.Lists;

    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.*;

    public class Test019 {

    public static void main(String[] args) {
    
        long start = System.currentTimeMillis();
        try {
            List<Long> resultList = new ArrayList<>();
            List<CompletableFuture<List<Long>>> tmp = new ArrayList();
            for (int i = 0; i < 4; i++) {
                final CompletableFuture<List<Long>> resultFuture = CompletableFuture.supplyAsync(() -> {
                    return dohandler();
                });
                tmp.add(resultFuture);
            }
    
            for (CompletableFuture<List<Long>> tmp2 : tmp) {
                resultList.addAll(tmp2.get());
            }
    
            System.out.println("结果:" + resultList + "耗时:" + (System.currentTimeMillis() - start));
        } catch (Exception e) {
            System.out.println("发生异常");
        }
    }
    
    public static List<Long> dohandler() {
        try {
            Thread.sleep(2500);
            return Lists.newArrayList(123L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }
    

    }

运行结果:
在这里插入图片描述

总结

也许我们可以通过死记硬背的方式学到很多“八股文”,但是往往这样学来的,终究是纸上学来终觉浅,如果能在真实的场景下应用的话,那么才能对此更有体会.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值