《重学Java高并发》同步转异步编程技巧与实战运用

简介: 《重学Java高并发》同步转异步编程技巧与实战运用

1、线程池+Future模式


笔者在公司中负责开发某一个产品时,需要实现一个告警模块,告警通知方式需要为钉钉群、电话短信等方式,并且及时时单一的告警方式,例如钉钉群告警,也需要同时发送到多个群(监控中心、业务项目组钉钉群),使监控告警能真正通知到各个相关方,确保人工及时处理跟进,避免事态进一步发展。


发送钉钉群告警信息的时序图如下:

8cde7b9f96dbd008e88b05cbee1595f7.png

发送到不同的钉钉群,这个过程完成可以并发,并发同步等待发送结果,即这个过程是一个同步场景,但可以转化成异步(多并发),即经典的同步转异步


要实现这个功能,我想大家第一时间会想到使用线程池+Future模式。

0502d7feda738c10f599cc7b7c5f618f.png

代码实现的关键点如下:


  • 创建一个线程池,请大家一定要使用自定义线程工厂,为创建的线程命名,如代码@2.
  • 两个任务,提交到线程池中,此过程是一个异步。注意:SendDingDingTalk是实现java.util.concurrent.Callable,即带返回值的任务。
  • 提交到线程池中的任务如果实现了java.util.concurrent.Callable,提交到线程池返回一个Future对象(凭证),通过调用Feture对象的get()方法,如果任务未完成,则会阻塞,即实现同步转异步调用,再转同步的调用效果,从而提高并发,提高性能。


2、CountDownLatch的妙用


使用线程池+Future模式,有时候会显得比较笨重,因为需要额外创建一个线程池,如果在一些轻量级场景(单线程+批量)场景下也希望将同步转异步,我们有其他办法没?


使用CountDownLatch!!!


接下来我们结合场景来说说如何使用CountDownLatch。


例如我们在对数据库数据进行清理时,通常会将数据进行分页(任务分批),然后创建多个子线程,主线程将任务分批后提交到子线程,等待子线程全部执行完成后,主线程打印执行日期,其时序图如下所示:

a303d5131b6c987e976ace315eee2e3d.png

主线程如何得知子线程执行完毕呢?在java中,通常的方案是 join,但juc框架中的CountDownLatch实现了与Thread.join相同的语义,其伪代码实现如下:

97df1a14c20d3eae7c45a81158770fd7.png

使用CountDownLatch的要点如下:


  • 首先会创建一个CountDownLatch,并且指定计数器,通常为子线程的个数。
  • 然后主线程向子线程提交任务,并且子线程在完成自己的工作后,调用CountDownLatch的countDown,计数器降一,“以此来表示子线程已处理完毕”。
  • 各个子线程异步执行,但最终还是要转为同步,因为主线程需要等待结果,故主线程需要调用CountDownLatch的await方法,进行阻塞,直到计数器为0。


关键中的关键:引入多个子线程并发执行,将同步任务转换为异步执行,但最终结果是必须等待所有子线程运行完毕,故此时异步又需要转回同步:


即CountDownLatch通过引入计数器以及countDown()方法与await()方法实现线程之间的协作,从而实现同步转异步。

相关文章
|
20天前
|
缓存 NoSQL Java
高并发场景秒杀抢购超卖Bug实战重现
在电商平台的秒杀活动中,高并发场景下的抢购超卖Bug是一个常见且棘手的问题。一旦处理不当,不仅会引发用户投诉,还会对商家的信誉和利益造成严重损害。本文将详细介绍秒杀抢购超卖Bug的背景历史、业务场景、底层原理以及Java代码实现,旨在帮助开发者更好地理解和解决这一问题。
52 12
|
15天前
|
Java
Java基础却常被忽略:全面讲解this的实战技巧!
本次分享来自于一道Java基础的面试试题,对this的各种妙用进行了深度讲解,并分析了一些关于this的常见面试陷阱,主要包括以下几方面内容: 1.什么是this 2.this的场景化使用案例 3.关于this的误区 4.总结与练习
|
1月前
|
Java 程序员
Java基础却常被忽略:全面讲解this的实战技巧!
小米,29岁程序员,分享Java中`this`关键字的用法。`this`代表当前对象引用,用于区分成员变量与局部变量、构造方法间调用、支持链式调用及作为参数传递。文章还探讨了`this`在静态方法和匿名内部类中的使用误区,并提供了练习题。
32 1
|
2月前
|
缓存 关系型数据库 MySQL
高并发架构系列:数据库主从同步的 3 种方案
本文详解高并发场景下数据库主从同步的三种解决方案:数据主从同步、数据库半同步复制、数据库中间件同步和缓存记录写key同步,旨在帮助解决数据一致性问题。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
高并发架构系列:数据库主从同步的 3 种方案
|
2月前
|
安全 Java 开发者
Java 多线程并发控制:深入理解与实战应用
《Java多线程并发控制:深入理解与实战应用》一书详细解析了Java多线程编程的核心概念、并发控制技术及其实战技巧,适合Java开发者深入学习和实践参考。
69 6
|
2月前
|
存储 安全 Java
Java多线程编程中的并发容器:深入解析与实战应用####
在本文中,我们将探讨Java多线程编程中的一个核心话题——并发容器。不同于传统单一线程环境下的数据结构,并发容器专为多线程场景设计,确保数据访问的线程安全性和高效性。我们将从基础概念出发,逐步深入到`java.util.concurrent`包下的核心并发容器实现,如`ConcurrentHashMap`、`CopyOnWriteArrayList`以及`BlockingQueue`等,通过实例代码演示其使用方法,并分析它们背后的设计原理与适用场景。无论你是Java并发编程的初学者还是希望深化理解的开发者,本文都将为你提供有价值的见解与实践指导。 --- ####
|
2月前
|
Go 计算机视觉
在Golang高并发环境中如何进行协程同步?
在此示例中,使用互斥锁来保护对共享计数器变量 c 的访问,确保并发的 HTTP 请求不会产生数据竞争。
48 3
|
2月前
|
Java 调度
Java 线程同步的四种方式,最全详解,建议收藏!
本文详细解析了Java线程同步的四种方式:synchronized关键字、ReentrantLock、原子变量和ThreadLocal,通过实例代码和对比分析,帮助你深入理解线程同步机制。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Java 线程同步的四种方式,最全详解,建议收藏!
|
7月前
|
缓存 NoSQL Java
Java高并发实战:利用线程池和Redis实现高效数据入库
Java高并发实战:利用线程池和Redis实现高效数据入库
540 0
|
5月前
|
监控 算法 Java
企业应用面临高并发等挑战,优化Java后台系统性能至关重要
随着互联网技术的发展,企业应用面临高并发等挑战,优化Java后台系统性能至关重要。本文提供三大技巧:1)优化JVM,如选用合适版本(如OpenJDK 11)、调整参数(如使用G1垃圾收集器)及监控性能;2)优化代码与算法,减少对象创建、合理使用集合及采用高效算法(如快速排序);3)数据库优化,包括索引、查询及分页策略改进,全面提升系统效能。
58 0