字节架构师:来说说Java异步调用的几种方式你都搞懂了吗?

Java 异步调用实践 本文介绍了线上业务中的一些异步调用实践经验,包含 IO 模型介绍、CompletableFuture 的基本使用、RPC 异步调用、异步 HTTP 客户端 Spring WebClient 的使用等。RPC 使用[前文介绍](https://mp.weixin.qq.com/s/rHjIKovZFKYQFB2PrlVPFg)的手写 [RPC 框架](https://github.com/ppphuang/rpc-spring-starter),该框架支持异步调用。... 阅读详情

在这里插入图片描述

字节架构师:来说说Java异步调用的几种方式你都搞懂了吗?

日常开发中,会经常遇到说,前台调服务,然后触发一个比较耗时的异步服务,且不用等异步任务的处理结果就对原服务进行返回。这里就涉及的Java异步调用的一个知识。下面本文尝试将Java异步调用的多种方式进行归纳。

一、通过创建新线程


首先的我们得认识到,**异步调用的本质,其实是通过开启一个新的线程来执行。**如以下例子:

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

    System.out.println("主线程 =====> 开始 =====> " + System.currentTimeMillis());

    new Thread(() -> {
        System.out.println("异步线程 =====> 开始 =====> " + System.currentTimeMillis());
        try{
            Thread.sleep(5000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("异步线程 =====> 结束 =====> " + System.currentTimeMillis());
    }).start();

    Thread.sleep(2000);

    System.out.println("主线程 =====> 结束 =====> " + System.currentTimeMillis());

}

数据结果如下所示,我们知道,System.currentTimeMillis()时间单位为ms。

主线程 =====> 开始 =====> 1627893837146
异步线程 =====> 开始 =====> 1627893837200
主线程 =====> 结束 =====> 1627893839205
异步线程 =====> 结束 =====> 1627893842212

我们通过线程休眠来达成主线程执行时间2秒左右,异步线程执行5秒左右的效果。通过打印出来的时间戳倒数第四位(秒位)我们可以看出,两个的线程执行总时间为5秒左右,符合异步执行的特征

以上是采用Runable实现多线程创建方式的lambda写法,关于的lambda知识,可参考Java Lambda 表达式;而关于多线程的多种实现方式,Java多线程事务管理一文有提及,可移步查看

二、通过线程池


因为异步任务的实现本质的由新线程来执行任务,所以通过线程池的也可以实现异步执行。写法同我们利用线程池开启多线程一样。但由于我们的目的不是执行多线程,而是异步执行任务,所以一般需要另外一个线程就够了。

因此区别于执行多线程任务的我们常用的newFixedThreadPool,在执行异步任务时,我们用newSingleThreadExecutor 来创建一个单个线程的线程池。

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

    System.out.println("主线程 =====> 开始 =====> " + System.currentTimeMillis());

    ExecutorService executorService = Executors.newSingleThreadExecutor();
    executorService.submit(()->{
        System.out.println("异步线程 =====> 开始 =====> " + System.currentTimeMillis());
        try{
            Thread.sleep(5000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("异步线程 =====> 结束 =====> " + System.currentTimeMillis());
    });
    executorService.shutdown(); // 回收线程池

    Thread.sleep(2000);

    System.out.println("主线程 =====> 结束 =====> " + System.currentTimeMillis());

}

执行结果如下:

主线程 =====> 开始 =====> 1627895467578
异步线程 =====> 开始 =====> 1627895467635
主线程 =====> 结束 =====> 1627895469644
异步线程 =====> 结束 =====> 1627895472649

可以看到,结果跟第一种结果是基本一致的。

温馨提示:不要忘记线程池的回收

三、通过@Async注解


我们都知道,SpringBoot项目有一个的很重要的特点就是的注解化。如果你的项目是SpringBoot,那就又多了一种选择——@Async注解。

使用起来也非常简单,将要异步执行的代码封装成一个方法,然后用@Async注解该方法,然后在主方法中直接调用就行。

@Test
public void mainThread() throws Exception{

    System.out.println("主线程 =====> 开始 =====> " + System.currentTimeMillis());
    collectionBill.asyncThread();
    Thread.sleep(2000);
    System.out.println("主线程 =====> 结束 =====> " + System.currentTimeMillis());

    Thread.sleep(4000); // 用于防止jvm停止,导致异步线程中断
}

@Async
public void asyncThread(){
    System.out.println("异步线程 =====> 开始 =====> " + System.currentTimeMillis());
    try{
        Thread.sleep(5000);
    }catch (InterruptedException e){
        e.printStackTrace();
    }
    System.out.println("异步线程 =====> 结束 =====> " + System.currentTimeMillis());
}

执行结果如下:

主线程 =====> 开始 =====> 1627897539948
异步线程 =====> 开始 =====> 1627897539956
主线程 =====> 结束 =====> 1627897541965
异步线程 =====> 结束 =====> 1627897544966

有以下两点需要注意:

  1. 类似@Tranctional注解,@Async注解的方法与调用方法不能在同一个类中,否则不生效
  2. JUnit框架的设计不考虑多线程场景,所以主线程退出后,子线程也会跟着立即退出,所以可以在后面加多线程休眠时间来观察异步线程的执行情况

四、通过CompletableFuture


CompletableFuture是JDK1.8的新特性,是对Future的扩展。CompletableFuture实现了CompletionStage接口和Future接口,增加了异步回调、流式处理、多个Future组合处理的能力。

实现代码如下:

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

    System.out.println("主线程 =====> 开始 =====> " + System.currentTimeMillis());

    ExecutorService executorService = Executors.newSingleThreadExecutor();
    CompletableFuture.runAsync(() ->{
        System.out.println("异步线程 =====> 开始 =====> " + System.currentTimeMillis());
        try{
            Thread.sleep(5000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("异步线程 =====> 结束 =====> " + System.currentTimeMillis());
    },executorService);
    executorService.shutdown(); // 回收线程池

    Thread.sleep(2000);

    System.out.println("主线程 =====> 结束 =====> " + System.currentTimeMillis());

}

同样可以实现类似的结果如下:

主线程 =====> 开始 =====> 1627898354914
异步线程 =====> 开始 =====> 1627898354977
主线程 =====> 结束 =====> 1627898356980
异步线程 =====> 结束 =====> 1627898359979

CompletableFuture有者非常强大的功能,能给我们带来非常丝滑的编程体验。后续会写一篇文章来详细介绍CompletableFuture

分类: [Java基础]

标签: [多线程]
在这里插入图片描述

Java异步调用接口实现方式 使用异步技术在大多情况下能够提升性能,而且会很显著,但不是盲目地使用多线程就能提高性能了。要合理考虑多个线程之间的协助,避免线程挂起阻塞太久,额外开启线程的性能开销不可忽视。可以在开启子线程的同时,主线程继续执行其它的操作,执行完成之后再判断子线程是否完成。如果想使用多线程提高系统的tps,一定要分析瓶颈所在之处。比如文中举的案例,如果瓶颈在接口响应的时间上,把调用A接口和调用B接口异步处理,并不能提升整体的性能,只能改进整体的响应时间。 阅读详情

相关推荐

java如何在普通方法中异步执行另外一个方法的几种方式

java如何在普通方法中异步执行另外一个方法的几种方式 1.触发器机制 2.自定义注解 ...

weixin_55915253的博客 2107

实战Java异步编程:CompletableFuture/Spring/MQ等高阶用法详解

"本文深度解析Java异步编程的4种核心实现方案,涵盖从基础到企业级的完整技术栈。通过对比Future/Callable原生线程模型、CompletableFuture链式编程、SpringBoot异步注解实战,以及RabbitMQ消息队列解耦方案,系统讲解不同场景下的异步处理最佳实践。文章包含完整代码示例和Spring线程池配置指南,特别针对高并发场景下的性能优化、消息可靠投递等难点提供解决方案,帮助开发者构建响应式、高吞吐的分布式系统。适合中高级Java工程师提升异步编程能力的实战指南。"

Zyw907155124的博客 2万+

xxl-job 源码运行解析,字节跳动Java架构师学习笔记

分享一套我整理的面试干货,这份文档结合了我多年的面试官经验,站在面试官的角度来告诉你,面试官提的那些问题他最想听到你给他的回答是什么,分享出来帮助那些对前途感到迷茫的朋友。

985

java 如何快速实现异步调用方法

在实现异步调用之前,我们先了解一下,什么是异步编程?什么场景下适用等等情况。我们都知道,在传统的同步编程中,当一个操作开始执行时,程序会阻塞并等待该操作完成,然后才能继续执行后续代码。这种阻塞等待的方式可能会导致程序响应性能下降,因为在等待的过程中无法同时处理其他任务。这种显而易见的,在某种耗时的场景下,就显得无用了,甚至很影响体验。如文件读写、网络请求或计算密集型任务,再如人脸融合特效等等,都是耗时的操作,这个时候,我们就需要异步编程了。

热爱技术,享受生活 3万+

掌控板玩板指南1:初识掌控板、扩展板、Mind+编辑器

掌控板、I/O扩展板入门

好乐无荒之地 1万+

手把手教你安装 Vivado2022.2(附安装包)

Vivado 2022.2版本与之前的版本相比,具有以下几个显著的优势:电源设计管理器(PDM):Vivado 2022.2引入了全新的电源设计管理器(PDM),这是一个下一代功耗评估平台,为Versal® 和 Kria™ SOM提供了准确一致的功耗估计能力。PDM是Versal产品家族的首选功耗评估工具,为Versal ACAP硬IP块提供增强向导,简化从XPE向PDM的迁移,帮助用户获得准确的功耗评估。

dpwkj的博客 2万+

字节架构师:来说说Java异步调用的几种方式

一、通过创建新线程 首先的我们得认识到,**异步调用的本质,其实是通过开启一个新的线程来执行。**如以下例子: public static void main(String[] args) throws Exception{ System.out.println("主线程 =====> 开始 =====> " + System.currentTimeMillis()); new Thread(() -> { System.out.println(.

weixin_42686892的博客 280

利用Solidworks2020将挖掘机装配体转换为URDF模型

利用Solidworks2020将挖掘机装配体转换为URDF模型一、下载sw_urdf_exporter插件 URDF(Universal Robot Description Format)——通用机器人描述格式,它是ROS里边使用的一种机器人的描述文件,包含的内容有:连杆、关节,运动学和动力学参数、可视化模型、碰撞检测模型等。 一、下载sw_urdf_exporter插件 ROS提供了SolidWorks转URDF的插件(下载链接)—sw2urdfSetup.exe,下载后点击安装,安装完成后就能在sol

weixin_48192326的博客 6100

一名百万薪资的java架构师应该具备什么技能?

所谓架构师,思考的是全局的东西,是如何组织你的系统,以达到业务要求,性能要求,具备可扩展性(scalability),可拓展性(extendability),前后兼容性等。可能涉及到的东西包括了从硬件到软件的方方面面,实在是一言难尽。 既然java架构师,首先你要是一个高级java攻狮城,熟练使用各种框架,并知道它们实现的原理。 jvm虚拟机原理、调优,懂得jvm能让你写出性能更好的代码;池技术,什么对象池,连接池,线程池…:;java反射技术,写框架必备的技术,但是有严重的性能问题,替代方案jav..

AI乔治 3193

Maya ACES工作流程配置(Arnold 及 RedShift 贴图配置规范-还原出SP-Aces流程下贴图正确的效果) PS还原Aces流程下渲染的图

*如果使用SP,项目工程如果新建的时候设置的就是Aces的流程的话,按规范正常导出即可,贴图会带上相对应的后缀,然后贴图导入材质球的时候会根据后缀自动设置相对应的色彩空间;**万一不是,就自己手动设置一下对应的色彩空间即可;然后点击选择当前的或者选择全部导入的贴图,点击右下角后,开始转换;我复制了一下,一个默认没有LUT的效果,然后另外一个是加载2个LUT后的还原效果,和渲染的效果应该是没有区别的,至少我没有看出明显的区别;把需要转换的贴图拖拽到左侧,然后右面选择需要转换到的相对应的色彩空间;...

Yuulily 7993

Python爬虫实战:微信小程序内容采集的全面指南

在移动互联网时代,微信小程序已成为企业和个人提供服务的重要渠道。小程序中包含了大量有价值的信息,但微信官方并未提供便捷的数据获取接口。本文将详细介绍如何使用Python爬虫技术采集微信小程序内容,包括最新技术方案、完整代码实现以及应对各种反爬机制的策略。小程序运行在微信封闭环境中,无法直接访问数据通信主要通过HTTPS加密传输内容动态加载,依赖JavaScript渲染微信有严格的反爬机制。

2201_76125261的博客 3116

全网最有深度的字节面经总结,一线架构师总结,GitHub火透了

小编精心为大家准备了一手资料以上Java高级架构资料、源码、笔记、视频。Dubbo、Redis、设计模式、Netty、zookeeper、Spring cloud、分布式、高并发等架构技术【附】架构书籍BAT面试的20道高频数据库问题解析Java面试宝典Netty实战算法BATJ面试要点及Java架构师进阶资料【附】架构书籍BAT面试的20道高频数据库问题解析Java面试宝典Netty实战算法[外链图片转存中…(img-bSFdp25K-1711492191688)]

2401_83703835的博客 690

【NLP】第十章:位置编码Positional Encoding

前面讲RNN时一般都会有一个ht的输出,这个输出就是样本与样本之间的信息,而且RNN是时序循环的,所以RNN本身的结构,在物理上,就自带词的前后顺序信息的。比如词never,不管never本身的词向量是什么,只要你在序列中排第一个位置,你的位置向量就是[0,1,01],你排第三个位置,你的位置向量就是[0.9,-0,4,0.2,1.0]。也所以,你可以理解为:embedding后的词嵌入,PE按照每个样本在sequence中的位置,把embedding后的词嵌入给扭转后,才送入attention的。

因为热爱所以坚持 1917

字节跳动移动架构师学习笔记(1)

UI这块知识是现今使用者最多的。当年火爆一时的Android入门培训,学会这小块知识就能随便找到不错的工作了。不过很显然现在远远不够了,拒绝无休止的CV,亲自去项目实战,读源码,研究原理吧!

2401_84121485的博客 639

ABAP 7.40 新语法介绍系列之六:使用 FILTER 关键字对 ABAP 内表进行过滤

笔者之前写过的关于 ABAP 740 新语法的文章:本文介绍另一个新的关键字:FILTER.FILTER 是 ABAP 740 中引入的一个关键字,用于简化数据操作,它能够将内部表(Internal Table)中的数据按特定的条件进行过滤,并生成一个新的内部表。FILTER 的引入旨在使代码更加现代化和高效,尤其是在面对大量数据需要过滤的情况下。传统上,开发人员可能需要使用 LOOP AT 结合条件判断来实现,但使用 FILTER 关键字后,代码显得更加简洁且易于维护。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1167

ASProxy64.dll导致jetbrains家的IDE都无法打开。

摘要:在Windows11系统中,JetBrains IDE无法启动,报错指向ASProxy64.dll文件。该第三方DLL被注入到JVM原生层,导致内存访问冲突(错误代码0xc0000005)。经排查发现此文件来自Astrill软件。解决方案为卸载Astrill后重启电脑,问题得以解决。该案例表明第三方DLL注入可能影响IDE正常运行,卸载相关软件是最直接的解决方法。(149字)

猿小白的博客 936

太牛了!字节跳动Java架构师学习笔记

本篇文章主要内容 数据缓存 为何要使用缓存 哪类数据适合缓存 缓存的利与弊 如何保证缓存和数据库一致性 不更新缓存,而是删除缓存 先操作缓存,还是先操作数据库 非要保证数据库和缓存数据强一致该怎么办 缓存和数据库一致性实战 实战:先删除缓存,再更新数据库 实战:先更新数据库,再删缓存 实战:缓存延时双删 实战:删除缓存重试机制 实战:读取binlog异步删除缓存 一面(技术面:算法+Redis+MySQL+网络) 给定m个不重复的字符 [a, b

m0_57501956的博客 180

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

一名十余年资深Java架构师的经验之谈

所谓架构师,思考的是全局的东西,是如何组织你的系统,以达到业务要求,性能要求,具备可扩展性(scalability),可拓展性(extendability),前后兼容性等。可能涉及到的东西包括了从硬件到软件的方方面面,实在是一言难尽。 要想往架构师的方向发展首先要知道架构师是什么?架构师是一个既需要掌控整体又需要洞悉局部瓶颈并依据具体的业务场景给出解决方案的团队领导型人物。一个架构师得需要足够的想像力,能把各种目标需求进行不同维度的扩展,为目标客户提供更为全面的需求清单。 架构师在软件开发的整个过程中起

wfxy123的博客 353

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

java基础程序题,字节跳动架构师讲解Java开发

看完美团、字节、腾讯这三家的一二三面试问题,是不是感觉问的特别多,可能咱们真的又得开启面试造火箭、工作拧螺丝的模式去准备下一次的面试了。开篇有提及我可是足足背下了Java互联网工程师面试1000题,多少还是有点用的呢,换汤不换药,不管面试官怎么问你,抓住本质即可!能读到此处的都是真爱Java互联网工程师面试1000题。

2401_84408249的博客 875

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

严禁外传,字节跳动 2022 春招 Java 岗位架构师面试题(暂定版)发布

前言: 说来说去废话也是那么多,今天小编实在是不想写前言了“原谅我一次”让我任性一回! 我还是喜欢直接入正题,直接给大家介绍一下今天的“主菜”《字节跳动 2022 春招 Java 岗位面试题(暂定版)》PDF 手册+近千套 Java 简历模板(从应届生到架构师) 严禁外传 面试题总览: 先给大家感受一下满满的诚意~~~ 基础的内容就不展示了,直接从 JVM 开始吧!扫码即可获取! JVM 相关面试题 内容 线程/并发编程 内容 网络协议相

qq_42986622的博客 1084

【Java高级】架构师需要具备的思维方式

架构师的核心能力在于多维思维的整合运用:系统思维(全局视角与动态平衡)、抽象思维(本质洞察与类比沟通)、演进思维(增量迭代与可逆决策)、折中思维(优先级管理)。优秀架构师需兼具业务价值驱动、风险前瞻防御、成本优化和跨团队协作能力,通过案例实践与持续反思,将技术能力升维为思维模型。其终极目标是成为业务与技术间的"翻译器",在复杂系统中实现动态平衡的最优解。(149字)

weixin_42548337的博客 763

字节跳动岗位薪酬体系曝光,看完感叹:不服不行,2024年阿里Java面试题及答案

即使你是一流大学毕业,与你同样水平的竞争者也层出不穷,在众多的竞争者中脱颖而出没有必然成功的方法,但努力过,肯定几率会更大。关于期权,期权是比较好的 2-1 才会有期权,一般 2-2 才有期权,关于期权:回购价格为市场价 8 折。字节跳动内部的绩效考核一共有八级,从低到高为 F、I、M-、M、M+、E、E+、O,并会进行强制分布,对应年终奖和月薪百分比的涨薪。头条是双月 OKR,可以在 lark 上看到所有人的 OKR,知道大家在做什么,你对齐的大目标是什么,支持对齐你的人在做什么。

m0_56169789的博客 4341

Java 架构师学习路线

Java 架构师学习路线

weixin_44138647的博客 2820

2025最新Java架构师面试题,已助我拿下3个大厂(美团、字节、饿了吗)的Offer

2025 年的互联网行业竞争越来越严峻,面试也是越来越难,一直以来我都想整理一套完美的,奈何难抽出时间,这套 1200+道的 Java 面试手册我整理了整整 1 个月,上传到 Git 上目前 star 数达到了 30K+(共 485 页,32W 字)下面将这份笔记的内容以截图的形式展示给大家!

m0_50180963的博客 1573

字节跳动移动架构师学习笔记

面试是一个不断学习、不断自我提升的过程,有机会还是出去面面,至少能想到查漏补缺效果,而且有些知识点,可能你自以为知道,但让你说,并不一定能说得很好。有些东西有压力才有动力,而学到的知识点,都是钱(因为技术人员大部分情况是根据你的能力来定级、来发薪水的),技多不压身。附上我的面试各大专题整理: 面试指南,满满的都是干货,希望对大家有帮助!《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!347506)]

2401_84149220的博客 1100

恭喜自己2024金三银四收到的第五个Offer:字节跳动Java研发岗

虽然我个人也经常自嘲,十年之后要去成为外卖专员,但实际上依靠自身的努力,是能够减少三十五岁之后的焦虑的,毕竟好的架构师并不多。架构师,是我们大部分技术人的职业目标,一名好的架构师来源于机遇(公司)、个人努力(吃得苦、肯钻研)、天分(真的热爱)的三者协作的结果,实践+机遇+努力才能助你成为优秀的架构师。如果你也想成为一名好的架构师,那或许这份Java成长笔记你需要阅读阅读,希望能够对你的职业发展有所帮助。4.多刷面试题。

2401_84002730的博客 795
上一篇: 关于学习数据库:“一对多、多对一处理和动态SQL”的问题?必须安排!
下一篇: java程序员一定要学会的骚操作“Linux下查看、卸载、安装jdk” !
Danny_java
博客等级 码龄5年 9粉丝 64原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值