简介

CountDownLatch是一个多线程同步工具类,在多线程环境中它允许多个线程处于等待状态,直到前面的线程执行结束。从类名上看CountDown既是数量递减的意思,我们可以把它理解为计数器。

核心方法

  • countDown():计数器递减方法。
  • await():使调用此方法的线程进入等待状态,直到计数器计数为0时主线程才会被唤醒。
  • await(long, TimeUnit):在await()方法的基础上增加了超时策略,若等待超时仍未有结果则会直接唤醒主线程运行。

CountDownLatch如何使用

在这里我们用一段简单的代码进行演示:

@Slf4j
public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(3);
        new Thread(() -> {
            log.info("hello this is thread one");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            countDownLatch.countDown();
        }).start();
        new Thread(() -> {
            log.info("hello this is thread two");
            countDownLatch.countDown();
        }).start();
        new Thread(() -> {
            log.info("hello this is thread three");
            countDownLatch.countDown();
        }).start();
        countDownLatch.await();
        log.info("say good bye!");
    }
}

由上面的代码可见,我们创建了一个CountDownLatch计数器为3和三个线程同步运行。在main主线程中调用了countDownLatch.await()方法使主线程进入阻塞。其中三个线程任务执行完毕后都会调用countDownLatch.countDown()方法对计数器进行递减,当三个线程任务都执行完毕后计数器计数值为0时主线程被唤醒。

注:在创建CountDownLatch实例时必须定义计数器值,一般相对较合理的用法是该值的定义需要经过合理的计算使计数值与需要并行的线程数相等,在每个线程执行完成后做计数递减,最终唤醒主线程继续执行。

  • CountDownLatch计数值设置大于线程数,那么最终所有线程都执行完了,而计数为递减到0那么主线程将会一直处于等待状态。
  • CountDownLatch计数值设置小于并发线程数,那么可能在部分线程未执行完毕时,计数就已经递减到0,则主线程会被提前唤醒。

CountDownLatch运行流程

如下图,主线程阻塞与唤醒的核心就是计数器,只有当所有线程执行完成计数逐个递减最终才会唤起await()阻塞中的主线程。

注:await()可以阻塞一个线程,也可以阻塞多个线程,如果是阻塞多个线程,那么在计数为0时将会唤醒所有被阻塞的线程。

运用场景

在简单了解完CountDownLatch的作用后,相信各位最终目的还是想了解如何去使用,在哪些场景下使用更加合适,接下来我就拿一个对账业务的场景详细分析一下。

相信现在很多平台都会对接银联、微信、支付宝等支付渠道做交易,那么在这样的场景下对账是不可避免的。对账通常都会在每日的凌晨去处理,一方面是凌晨时间点多数平台访问量都会较小,服务器压力也比较轻松,而且此时出账也比较合理,所以在这个时间点做对账也是一个大数据量计算的操作。

上面讲这么多好像都没说到重点,在处理对账之前首先我们肯定是需要通过各个支付渠道获取对账单文件,那么该如何操作呢?

  • 对账文件下载(第一阶段):在这种情况下可以设计三个任务并发去获取对账文件,使用CountDownLatch阻塞主线程,等待三个任务都获取到文件的时候做计数递减,最终唤醒主线将标记本阶段处理完成,并发起进入下一阶段的通知。
  • 对账文件解析(第二阶段):在上个阶段已下载完成的文件文件中,此阶段要做的就是解析文件。由于三个渠道都是不同的厂家那么文件的内容格式肯定都是不一样的,这时候我们又可以使用CountDownLatch启动三个线程分别去解析各自的对账文件,最终将文件内容转换为业务所需的数据统一格式入库,在三个任务都入库完成后主线程又被唤醒标记完成后,通知下一阶段开始进入工作。
  • 对账结算(第三阶段):在上一阶段的数据入库完成后,此阶段要做的就是比对每一笔交易是否准确,一般都是按单号与交易渠道比对交易的金额是否一致,如果金额一致则该笔交易结算成功,否则将交易判定为异常交易,并入库处理。由上面的流程分析我们就可以设计相对合理的CountDownLatch计数,结合Semaphore信号量控制并发量同时对对比交易单做并发处理,最终带所有交易单处理完成后唤醒主线程标记对账完成,并通知下一阶段进行出账。
  • 出账(第四阶段):通常平台在对账完成后会进行出账,也就是按照平台的业务规则出具相关的账单方便财务人员进行统计。

总结

多线程并发的情况下需要做好同步处理,结合CountDownLatch充分的运用到业务场景当中还是挺有必要的,凡是需要在多个任务执行完成后再去做另一件事的情况都可以考虑使用CountDownLatch,合理使用但请不要滥用,特别上面也提到过计数值需要确定,否则可能导致多任务无法做到同步甚至造成主线程无限等待。

到此这篇关于Java多线程同步工具类CountDownLatch详解的文章就介绍到这了,更多相关Java CountDownLatch内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Java多线程同步工具类CountDownLatch详解的更多相关文章

  1. iOS:核心图像和多线程应用程序

    我试图以最有效的方式运行一些核心图像过滤器.试图避免内存警告和崩溃,这是我在渲染大图像时得到的.我正在看Apple的核心图像编程指南.关于多线程,它说:“每个线程必须创建自己的CIFilter对象.否则,你的应用程序可能会出现意外行为.”这是什么意思?我实际上是试图在后台线程上运行我的过滤器,所以我可以在主线程上运行HUD(见下文).这在coreImage的上下文中是否有意义?

  2. ios – 意外的核心数据多线程违规

    我正在使用苹果的并发核心数据调试器.-com.apple.CoreData.ConcurrencyDebug1有时候我得到__Multithreading_Violation_AllThatIsLeftToUsIsHonor__,即使我几乎肯定线程没有被违反.这是发生异常的代码的一部分(代码是扩展NSManagedobject的协议的一部分):代码在上下文的执行:块中执行.这里是线程信息:和调试器

  3. ios – UIGraphicsBeginImageContextWithOptions和多线程

    我对UIGraphicsBeginImageContextWithOptions和线程有点困惑,因为根据UIKitFunctionReferenceUIGraphicsBeginImageContextWithOptions应该只在主线程上调用.当被调用时,它创建一个基于位图的上下文,可以使用CoreGraphics的函数或者像-drawInRect这样的方法来处理:对于UIImage,-draw

  4. Swift之dispatch_source实现多线程定时关闭功能

    由于在项目中需要用到定时关闭音频功能,本来打算用NSTimer的,可是写起来并不是那么精简好用,所以又在网上找到相关的实例,结合自己项目需要,就写出了如下代码,还请大家指教,废话不多说:

  5. swift 多线程实现

  6. swift_多线程基础_最简单用法GCD, NSOperationQueue, NSThread

    ////ViewController.swift//study1-1//Createdbyadminon15/12/28.//copyright2015年admin.Allrightsreserved.//importUIKitclassViewController:UIViewController{@IBOutletvarmyLable:UILabel?@IBActionfuncclickBut

  7. swift__多线程GCD详解

    有以下*-disPATCH_QUEUE_PRIORITY_HIGH:*-disPATCH_QUEUE_PRIORITY_DEFAULT:多用默认*-disPATCH_QUEUE_PRIORITY_LOW:*-disPATCH_QUEUE_PRIORITY_BACKGROUND:*第二个参数为预留参数,一般为0*/letmyQueue:dispatch_queue_t=dispatch_get_global_queue//用异步的方式运行队列里的任务dispatch_async//-------------

  8. Swift - 多线程实现方式3 - Grand Central DispatchGCD

    dispatchqueue可以是并发的或串行的。dispatch_suspend后,追加到DispatchQueue中尚未执行的任务在此之后停止执行。6//创建并行队列conQueue:dispatch_queue_t=dispatch_queue_create//暂停一个队列dispatch_suspend//继续队列dispatch_resume6,dispatch_once一次执行保证dispatch_once中的代码块在应用程序里面只执行一次,无论是不是多线程。注意,我们不能(直接)取消我们已经提

  9. 【Swift】三种多线程处理方式

    )Threadbtn.frame=CGRectMakeThreadbtn.setTitle//普通状态下的文字Threadbtn.setTitle//触摸状态下的文字letmethod:Selector=methodarr[index!]Threadbtn.addTargetself.view.addSubview;}}overridefuncdidReceiveMemoryWarning(){super.didReceiveMemoryWarning()}//1.NSThread线程functestNS

  10. Swift多线程之GCD

    学自:http://www.jianshu.com/p/2598a4e9c139

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部