判断线程/任务是否全部执行完成

news2024/11/16 5:23:30

判断线程/任务是否全部执行完成

需求

从网络上下载多个文件(可能会有很多)。最后将所有文件打包为一个压缩包。

思路

  1. 考虑可能有很多文件,所以采用多线程,一个线程去下载一个资源。
  2. 最后再将所有文件夹进行打包。

问题

打包后发现压缩包类的文件,跟实际的下载下来的文件数量不一致。很奇怪🤣

排查发现,在进行打包的时候实际上文件夹内的文件数量并不是最终的数量。由此可以判断出我在进行打包的时候我的下载线程还有未执行完成的。

解决方案

方案1-CountDownLatch(推荐)

CountDownLatch:用于实现线程间的协同。它允许一个或多个线程等待其他线程完成操作。

他是在初始化时指定一个计数值,每个线程完成任务时将这个计数值减一,当计数值达到零时,等待的线程被唤醒继续执行。

重要方法
  • CountDownLatch(int size)

    • 构造函数
  • void countDown()

    • 每次一个线程完成任务时,调用此方法将计数值减一
  • void await() throws InterruptedException

    • 当前线程调用此方法时会被阻塞,直到计数值减为零。如果在等待过程中被中断,将抛出 InterruptedException
  • boolean await(long timeout, TimeUnit unit) throws

    • InterruptedException

      类似于 await() 方法,但允许设置等待的最大时间。如果在指定时间内计数值减为零,返回 true;如果超时,返回 false

样例
@Test
public void testCountDownLatch(){
    int count = 5;
    CountDownLatch countDownLatch = new CountDownLatch(count);
    for (int l = 0; l < count; l++) {
        new Thread(()-> {
            log.info("执行完成");
            // 每个线程执行完成后执行countDown 使得countDownLatch可以-1
            countDownLatch.countDown();
        }).start();
    }
    try {
        // for 循环结束后可能其中一部分线程并没有结束,这里使用await,使得我们的主线程阻塞住,直到所有的线程执行完成也就是countDownLatch 为0的时候。
        // await(long timeout, TimeUnit unit) 这里其实也可以设置一个超时时间来避免长时间没有执行完成的问题。
        countDownLatch.await();
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
}
缺点

CountDownLatch 他是一次性的,不能重复使用

方案2-CyclicBarrier

CyclicBarrier:允许一组线程在达到某个屏障点时相互等待,并在所有线程都到达时继续执行。

它是一个可以重复使用的循环屏障,一次用完后,可以通过reset来重置屏障点的数量。

重要方法
  • CyclicBarrier(int parties)

    • 构造方法,创建一个 CyclicBarrier 实例,指定屏障点的数量(parties)。

    • parties 表示需要等待的线程数量,即当调用 await() 方法的次数达到 parties 时,所有线程将继续执行。

  • void await()

    • 当线程到达屏障点时调用此方法,告诉屏障它已经到达,然后等待其他线程。
    • 如果当前调用是最后一个到达屏障点的线程,则屏障打开,所有等待的线程被释放,可以继续执行。
  • boolean await(long timeout, TimeUnit unit)

    • 类似于 await() 方法,但是允许设置超时时间,超过指定的时间后如果仍然有线程未到达屏障点,将抛出 TimeoutException
  • void reset()

    • 重置屏障,将屏障恢复到初始状态。即使有一些线程正在等待,它们也会被唤醒并抛出 BrokenBarrierException,表示屏障已经被重置。
样例
@Test
public void testCyclicBarrier() throws BrokenBarrierException, InterruptedException {
    int count = 5;
    // 这里可以设置一个回调,当所有任务执行完成后再执行。
    CyclicBarrier cyclicBarrier = new CyclicBarrier(count,()->{
        log.info("所有线程执行完成");
    });
    for (int l = 0; l < count; l++) {
        new Thread(()-> {
            log.info("开始等待");
            try {
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } catch (BrokenBarrierException e) {
                throw new RuntimeException(e);
            }
            log.info("执行完成");
        }).start();
    }
    // 如果使用junit来进行测试的话,这里其实会直接退出的。可以使用对主线程进行屏障。从而导致junit单元测试不会退出。
    cyclicBarrier.await();
}

image-20240122161625173

它是可以使线程都先阻塞住,然后等屏蔽点到达一定的数据的时候就解除所有屏蔽点,使得可以继续执行。

缺点

使用起来不如CountDownLatch方便,而且上面那个样例中在主线程使用cyclicBarrier.await()其实就会导致屏蔽点+1所有最后只输出了4个执行完成。

这里太懒了,我们没有细究(感觉使用不多)。🤣

方案3-CompletableFuture(推荐)

CompletableFuture 是 Java 8 引入的一个强大的异步编程工具,用于简化异步操作的处理和组合。

这里我们使用一个叫CompletableFuture.allOf(CompletableFuture...)的方法。

重要方法
  • CompletableFuture.allOf(CompletableFuture...)
    • CompletableFuture 提供的一个方法,他是一个可变参数。用于等待传入的所有 CompletableFuture 完成,当所有的CompletableFuture都完成时,新的CompletableFuture 也完成。
  • join()
    • CompletableFuture 类中的一个方法,用于等待异步操作的完成并获取结果。它类似于 get() 方法,但是不会抛出 checked exception。在使用 join() 时,如果异步操作抛出了异常,它会包装成 CompletionException
样例
@Test
public void testCompletableFuture(){
    // 使用一个集合来记录所有的异步任务。
    List<CompletableFuture<?>> list = new ArrayList<>();
    for (int i = 0; i < 5; i++) {
        list.add(CompletableFuture.runAsync(()-> log.info("执行完成")));
    }
    // 最后创建一个新的来记录所有的异步任务是否已经执行完成。
    CompletableFuture.allOf(list.toArray(new CompletableFuture[0])).join();
}
注意

这里所有的CompletableFuture都没有指定线程池,所有他这里是使用的forkJoinPool。最好不要使用内置的这个线程池,可以自定义一个,然后在创建CompletableFuture的时候进行指定。

总结

注意

这里所有的CompletableFuture都没有指定线程池,所有他这里是使用的forkJoinPool。最好不要使用内置的这个线程池,可以自定义一个,然后在创建CompletableFuture的时候进行指定。

总结

我感觉方案3好用一些。但是如果不放心使用异步任务的话,直接使用方案1即可。都可以实现功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1402776.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue3自定义按钮点击变颜色实现(多选功能)

实现效果图&#xff1a; 默认选中第一个按钮&#xff0c;未选中按钮为粉色&#xff0c;点击时颜色变为红色 利用动态类名&#xff0c;当定义isChange数值和下标index相同时&#xff0c;赋予act类名&#xff0c;实现变色效果 <template><div class"page"&…

logstack 日志技术栈-04-opensource 开源工具 SigNoz+Graylog

3. SigNoz SigNoz 是一个日志收集和分析工具&#xff0c;可以收集和管理来自各种来源的日志、指标、跟踪和异常。 它为使用 OpenTelemetry 检测应用程序提供本机支持&#xff0c;以防止供应商锁定&#xff0c;将收集到的数据存储在 ClickHouse 中&#xff0c;然后在用户友好的…

OR36 链表的回文结构

目录 一、思路 二、代码 一、思路 找到中间节点 后半部分逆置链表 定义两个指针&#xff0c;一个从头开始出发 一个从中间位置开始出发 但是注意&#xff1a;链表个数可能是奇数或者偶数&#xff0c;需要注意中间节点的计算 二、代码 struct ListNode* reverseList(str…

api网关-kong

选型 api网关相关功能 服务的路由 动态路由负载均衡 服务发现 限流 熔断、降级 流量管理 黑白名单反爬策略 控制台&#xff1a;通过清晰的UI界面对网关集群进行各项配置。 集群管理&#xff1a;Goku网关节点是无状态的&#xff0c;配置信息自动同步&#xff0c;支持节点水…

DC-7靶机做题记录

靶机下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1w2c_QKd_hOoR2AzNrdZjMg?pwdtdky 提取码&#xff1a;tdky 参考&#xff1a; DC7靶机地址&#xff1a;http://www.five86.com/downloads/DC-7.zipDC7靶场介绍: https://www.vulnhub.com/entry/dc-7,356/…

纽约时报:揭秘美国比特币矿场背后的中国主人

原文标题&#xff1a;《This NYU Student Owns a $6 Million Crypto Mine. His Secret Is Out》 作者&#xff1a;Michael Forsythe、Gabriel J.X. Dance&#xff0c;纽约时报 编译&#xff1a;Carl&#xff0c;Techub News 下载Techub News APP 查看更多Web3相关信息 发生在…

搜索与图论第五期 拓扑序列

前言 拓扑排序是非常重要的一部分&#xff0c;希望大家都能够手撕代码&#xff01;&#xff01;&#xff01;&#xff08;嘿嘿嘿&#xff09; 一、拓扑排序定义&#xff08;百度须知嘿嘿嘿&#xff09; 拓扑排序 拓扑排序是一种对有向无环图&#xff08;Directed Acyclic Gra…

前后端分离,使用vue3整合SpringSecurity加JWT实现登录校验

前段时间写了一篇spring security的详细入门&#xff0c;但是没有联系实际。 所以这次在真实的项目中来演示一下怎样使用springsecurity来实现我们最常用的登录校验。本次演示使用现在市面上最常见的开发方式&#xff0c;前后端分离开发。前端使用vue3进行构建&#xff0c;用到…

ubuntu 安装protobuf

apt 安装 sudo apt install protobuf-compiler 编译安装 – 方式1 资料链接&#xff1a;ubuntu环境 安装ncnn_ubuntu ncnn_jbyyy、的博客-CSDN博客 git clone https://github.com/google/protobuf.git cd protobuf git submodule update --init --recursive ./autogen.sh …

如何在 Ubuntu 22.04 上安装 Linux、Apache、MySQL、PHP (LAMP) 堆栈

前些天发现了一个人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;最重要的屌图甚多&#xff0c;忍不住分享一下给大家。点击跳转到网站。 如何在 Ubuntu 22.04 上安装 Linux、Apache、MySQL、PHP (LAMP) 堆栈 介绍 “LAMP”堆栈是一组开源软件&#…

Unity 工厂方法模式(实例详解)

文章目录 在Unity中&#xff0c;工厂方法模式是一种创建对象的常用设计模式&#xff0c;它提供了一个接口用于创建对象&#xff0c;而具体的产品类是由子类决定的。这样可以将对象的创建过程与使用过程解耦&#xff0c;使得代码更加灵活和可扩展。 工厂模式的主要优点如下&…

一文了解Stream流(超详细+干货满满)

Stream流是对集合对象功能的增强&#xff0c;专注于对集合对象进行各种便利、高效的聚合操作或者大批量数据操作 //java.util.Collection.stream()方法用集合创建流 //Arrays.asList是将数组转化成List集合的方法 List<String> list Arrays.asList("hello",&…

LeetCode面试题02.07链表相交

力扣题目链接 思想&#xff08;数学&#xff09;&#xff1a;设链表A的长度为a&#xff0c;链表B的长度为b&#xff0c;A到交点D的距离为c&#xff0c;B到交点D的距离为d。显然可以得到两者相交链表的长度为&#xff1a;a - c b - d ,变换一下式子得到&#xff1a;a d b c…

Android学习之路(23)组件化框架ARouter的使用

一、功能介绍 支持直接解析标准URL进行跳转&#xff0c;并自动注入参数到目标页面中支持多模块工程使用支持添加多个拦截器&#xff0c;自定义拦截顺序支持依赖注入&#xff0c;可单独作为依赖注入框架使用支持InstantRun支持MultiDex(Google方案)映射关系按组分类、多级管理&…

应用层—HTTPS详解(对称加密、非对称加密、密钥……)

文章目录 HTTPS什么是 HTTPSHTTPS 如何加密HTTPS 的工作过程对称加密非对称加密 HTTPS 什么是 HTTPS HTTPS 也是一个应用层的协议。是在 HTTP 协议的基础上引入的一个加密层。 由来&#xff1a;HTTP 协议内容都是按照文本的方式明纹传输&#xff0c;这就导致在传输过程中出现…

重磅来袭“2024粤港澳电子展”覆盖电子信息完整产业链

2024年4月份粤港澳地区将举办一场规模盛大的电子信息产业博览会。这场展会占地面积高达10万平米&#xff0c;设立了多个展馆&#xff0c;涵盖了智慧家庭、新型显示、高端半导体、信创、大数据与存储、国防军工、人工智能、绿色消费电子、基础元器件等行业热点主题。 CITE品牌创…

开源运维监控工具Uptime Kuma本地部署并结合内网穿透实现公网访问

目录 主要功能 一、前期准备 本教程环境为&#xff1a;Centos7&#xff0c;可以跑Docker的系统都可以使用本教程安装。 本教程使用Docker部署服务&#xff0c;如何安装Docker详见&#xff1a; 二、Docker部署Uptime Kuma 三、实现公网查看网站监控 四、使用固定公网地址…

Pycharm连接远程服务器遇到的问题

文章目录 问题一 pycharm always "uploading pycharm helpers" to same remote python interpreter when starts问题二 [Errno 2] No such file or directory/root/miniconda3/bin/python: cant open file/root/. pycharm helpers/virtualenv-20. 24.5.pyz: 根据大佬…

终于把ESB升级说清楚啦!

我们先前已经介绍了iPaaS和API。本期我们将为大家介绍企业集成的重要工具之一——ESB。 【干货分享】终于有人把ESB升级说清楚啦&#xff01; ESB是什么&#xff1f; 随着信息化发展不断深入&#xff0c;企业在不同的阶段引入了不同的应用、系统和软件。这些原始的应用系统互不…

第04章_IDEA的安装与使用(下)(IDEA断点调试,IDEA常用插件)

文章目录 第04章_IDEA的安装与使用&#xff08;下&#xff09;8. 快捷键的使用8.1 常用快捷键8.2 查看快捷键1、已知快捷键操作名&#xff0c;未知快捷键2、已知快捷键&#xff0c;不知道对应的操作名 8.3 自定义快捷键8.4 使用其它平台快捷键 9. IDEA断点调试(Debug)9.1 为什么…