当前位置: 首页 > news >正文

【SpringBoot】20 同步调用、异步调用、异步回调

Git仓库

https://gitee.com/Lin_DH/system

介绍

同步调用:指程序在执行时,调用方需要等待函数调用返回结果后,才能继续执行下一步操作,是一种阻塞式调用。
异步调用:指程序在执行时,调用方在调用函数后立即返回,不需要等待函数调用返回结果,可以直接执行下一步操作,当函数执行完成后,会通过回调或其他方式通知调用方,得到返回结果。
回调:在调用一个函数后,需要在函数执行中或执行后,将执行结果或状态返回给调用者。

代码实现

第一步:启动类上添加 @EnableAsync 注解,开启异步功能。

@EnableAsync
@SpringBootApplication
public class SystemApplication extends SpringBootServletInitializer {}

同步调用

第二步:添加同步调用业务逻辑
注:@Async 注解不能修饰的 static 修饰的函数,该类型的函数异步调用不会生效。

package com.lm.system.task;import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import java.util.Random;/*** 同步调用* @author DUHAOLIN* @date 2024/10/17*/
@Slf4j
@Component
public class SyncTask {public static Random random = new Random();public void one() throws InterruptedException {commonTask("一");}public void two() throws InterruptedException {commonTask("二");}public void three() throws InterruptedException {commonTask("三");}public void commonTask(String s) throws InterruptedException {log.info("开始执行任务" + s);long startTime = System.currentTimeMillis();Thread.sleep(random.nextInt(10000));long endTime = System.currentTimeMillis();log.info("完成任务" + s + ",耗时:" + (endTime - startTime) + "毫秒");}}

第三步:测试类添加同步调用的测试方法

SystemApplicationTests.java

@Slf4j
@SpringBootTest(classes = SystemApplication.class)
class SystemApplicationTests {@Resourceprivate SyncTask syncTask;@Testpublic void syncTest() throws InterruptedException {long startTime = System.currentTimeMillis();syncTask.one();syncTask.two();syncTask.three();long endTime = System.currentTimeMillis();log.info("任务总耗时:" + (endTime - startTime) + "毫秒");}}

异步调用

第四步:添加异步调用业务逻辑

AsyncTask.java

/*** 异步调用* @author DUHAOLIN* @date 2024/10/17*/
@Slf4j
@Component
public class AsyncTask {public static Random random = new Random();@Asyncpublic void one() throws InterruptedException {commonTask("一");}@Asyncpublic void two() throws InterruptedException {commonTask("二");}@Asyncpublic void three() throws InterruptedException {commonTask("三");}public void commonTask(String s) throws InterruptedException {log.info("开始执行任务" + s);long startTime = System.currentTimeMillis();Thread.sleep(random.nextInt(10000));long endTime = System.currentTimeMillis();log.info("完成任务" + s + ",耗时:" + (endTime - startTime) + "毫秒");}}

第五步:测试类添加异步调用的测试方法

SystemApplicationTests.java

@Resource
private AsyncTask asyncTask;@Test
public void asyncTest() throws InterruptedException {long startTime = System.currentTimeMillis();asyncTask.one();asyncTask.two();asyncTask.three();long endTime = System.currentTimeMillis();log.info("任务总耗时:" + (endTime - startTime) + "毫秒");
}

异步回调(常用)

第六步:添加异步回调业务逻辑

AsyncCallBackTask.java

package com.lm.system.task;import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;import java.util.Random;package com.lm.system.task;import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;import java.util.Random;
import java.util.concurrent.CompletableFuture;/*** 异步回调* @author DUHAOLIN* @date 2024/10/17*/
@Slf4j
@Component
public class AsyncCallBackTask {public static Random random = new Random();@Asyncpublic CompletableFuture<String> one() throws InterruptedException {log.info("开始执行任务一");long startTime = System.currentTimeMillis();Thread.sleep(random.nextInt(10000));long endTime = System.currentTimeMillis();log.info("完成任务一,耗时:" + (endTime - startTime) + "毫秒");return CompletableFuture.completedFuture("任务一执行完成");}@Asyncpublic CompletableFuture<String> two() throws InterruptedException {log.info("开始执行任务二");long startTime = System.currentTimeMillis();Thread.sleep(random.nextInt(10000));long endTime = System.currentTimeMillis();log.info("完成任务二,耗时:" + (endTime - startTime) + "毫秒");return CompletableFuture.completedFuture("任务二执行完成");}@Asyncpublic CompletableFuture<String> three() throws InterruptedException {log.info("开始执行任务三");long startTime = System.currentTimeMillis();Thread.sleep(random.nextInt(10000));long endTime = System.currentTimeMillis();log.info("完成任务三,耗时:" + (endTime - startTime) + "毫秒");return CompletableFuture.completedFuture("任务三执行完成");}}

第七步:测试类添加异步回调的测试方法

SystemApplicationTests.java

@Resourceprivate AsyncCallBackTask asyncCallBackTask;@Testpublic void asyncCallBackTaskTest() throws InterruptedException {long startTime = System.currentTimeMillis();CompletableFuture<String> one = asyncCallBackTask.one();CompletableFuture<String> two = asyncCallBackTask.two();CompletableFuture<String> three = asyncCallBackTask.three();CompletableFuture.allOf(one, two, three).join();long endTime = System.currentTimeMillis();log.info("任务总耗时:" + (endTime - startTime) + "毫秒");}

效果图

同步调用
在这里插入图片描述
异步调用
执行完异步调用,只有任务的部分相关输出,任务的执行顺序也是乱序的。
在这里插入图片描述
异步回调
在这里插入图片描述

异步任务线程池配置

介绍

当我们用异步调用或异步回调进行并发操作时,加速了任务的执行效率,但是如果只是直接简单的创建来使用,可能会碰到一些问题和风险。当接口被频繁调用,异步任务创建的数量达到一定量级,可能会导致内存溢出,此时我们就需要对创建异步任务的操作,加上线程池的相关配置。
在这里插入图片描述
queueCapacity:缓冲队列的容量,默认为INT的最大值(2的31次方-1)
maxSize:允许的最大线程数,默认为INT的最大值(2的31次方-1)

具体配置

在这里插入图片描述

application.yml

spring:task:execution:pool:core-size: 2 #线程池创建时的初始化线程数,默认为8max-size: 5 #线程池的最大线程数,默认为int最大值queue-capacity: 10 #用来缓冲执行任务的队列,默认为int最大值keep-alive: 60s #线程终止前允许保持空闲的时间,默认为60sallow-core-thread-timeout: true #是否允许核心线程超时shutdown:await-termination: false #是否等待剩余任务完成后才关闭应用await-termination-period: #等待剩余任务完成的最大时间thread-name-prefix: task- #线程名的前缀,设置好了之后可以方便我们在日志中查看处理任务所在的线程池

application.Properties

spring.task.execution.pool.core-size=2
spring.task.execution.pool.max-size=5
spring.task.execution.pool.queue-capacity=10
spring.task.execution.pool.keep-alive=60s
spring.task.execution.pool.allow-core-thread-timeout=true
spring.task.execution.shutdown.await-termination=false
spring.task.execution.shutdown.await-termination-period=
spring.task.execution.thread-name-prefix=task-

效果图

再次执行异步回调方法,得到如下效果图。
当前配置的初始化线程数为2,最大线程数为5,缓存队列为10,只有当缓存队列满且当前线程数小于最大线程数时,才会申请新的线程来执行任务(如:缓存队列为11,初始化线程数为2,最大线程数为5)。
在这里插入图片描述

项目结构图

在这里插入图片描述

参考资料

Spring Boot 2.x基础教程:使用@Async实现异步调用【https://www.didispace.com/spring-boot-2/8-3-async-1.html】
Spring Boot 2.x基础教程:配置@Async异步任务的线程池【https://www.didispace.com/spring-boot-2/8-3-async-2.html】

相关文章:

【SpringBoot】20 同步调用、异步调用、异步回调

Git仓库 https://gitee.com/Lin_DH/system 介绍 同步调用&#xff1a;指程序在执行时&#xff0c;调用方需要等待函数调用返回结果后&#xff0c;才能继续执行下一步操作&#xff0c;是一种阻塞式调用。 异步调用&#xff1a;指程序在执行时&#xff0c;调用方在调用函数后立…...

【Excel】数据透视表分析方法大全

数据透视表的最常用的功能是分类汇总&#xff0c;其实它还有很强大的数据分析功能。在数据透视表右键菜单的值显示方式中&#xff0c;可以看到有14个很实用的分析选项。 1、总计的百分比 作用&#xff1a;透视表中每一个数字&#xff08;包括汇总行、总计行&#xff09;占右…...

深度学习在边缘检测中的应用及代码分析

摘要&#xff1a; 本文深入探讨了深度学习在边缘检测领域的应用。首先介绍了边缘检测的基本概念和传统方法的局限性&#xff0c;然后详细阐述了基于深度学习的边缘检测模型&#xff0c;包括其网络结构、训练方法和优势。文中分析了不同的深度学习架构在边缘检测中的性能表现&am…...

k8s 1.28.2 集群部署 docker registry 接入 MinIO 存储

文章目录 [toc]docker registry 部署生成 htpasswd 文件生成 secret 文件 生成 registry 配置文件创建 service创建 statefulset创建 ingress验证 docker registry docker registry 监控docker registry ui docker registry dockerfile docker registry 配置文件 S3 storage dr…...

常用的生物医药专利查询数据库及网站(很全!)

生物医药专利信息检索是药物研发前期不可或缺的一步&#xff0c;通过对国内外生物医药专利网站信息查询&#xff0c;可详细了解其专利技术&#xff0c;进而有效降低药物研发过程中的风险。 目前主要使用的生物医药专利查询网站分为两大类&#xff0c;一个是免费生物医药专利查询…...

「QT」几何数据类 之 QPolygon 多边形类

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「QT」QT5程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasolid…...

写给初学者的React Native 全栈开发实战班

React Native 全栈开发实战班 亲爱的同学们&#xff1a; 很高兴在这里与大家相聚&#xff01;我是你们的讲师&#xff0c;将带领大家一起踏上 React Native 移动开发的学习之旅。 为什么选择 React Native&#xff1f; 在这个移动互联网时代&#xff0c;App 开发工程师已经…...

工作和学习遇到的技术问题

写在前面 记录工作和学习遇到的技术问题,以求再次遇到可以快速解决。 1&#xff1a;Ubuntu TSL换源报错&#xff1a;Err:1 http://mirrors.aliyun.com/ubuntu focal InRelease 执行如下操作&#xff08;已经操作的则忽略&#xff09;&#xff0c;首先在文件/etc/apt/sources…...

如何解决JAVA程序通过obloader并发导数导致系统夯住的问题 | OceanBase 运维实践

案例背景 某保险机构客户的数据中台&#xff0c;自系统上线后不久&#xff0c;会定期的用 obload 工具从上游业务系统导入数据至OceanBase数据库。但&#xff0c;不久便遇到了应用服务器的 Memory 与 CPU 资源占用持续攀升&#xff0c;最终导致系统夯住而不可用的异常。 memo…...

Git零基础到入门

一、开始工作区 clone: 克隆一个仓库到新的目录。 git clone https://github.com/username/repository.git init: 创建一个新的空 Git 仓库或重新初始化现有的仓库,新建git项目。 //创建项目两种方式 //一、本地项目自己创建项目&#xff0c;先创建好工作文件夹&#xff0c;通…...

HTTP 1.0、HTTP 1.1 和 HTTP 2.0 区别

HTTP 1.0、HTTP 1.1 和 HTTP 2.0 是超文本传输协议&#xff08;HTTP&#xff09;不同版本的规范&#xff0c;各自进行了多项更新和改进&#xff1a; 1. HTTP/1.0 单一请求-响应&#xff1a;每次请求都需要建立一个新的 TCP 连接&#xff0c;完成后立即断开。无状态连接&#…...

解决 ElSelect 数据量大导致加载速度慢

遇到一个性能相关的问题&#xff0c;使用 Element Plus 的 <ElSelect> 组件在数据量很大时&#xff0c;加载速度变慢。 下面简单分析下原因&#xff0c;并提供了一些解决方法。 1. 问题分析 1、大量 DOM 节点渲染 问题&#xff1a;当数据量非常大时&#xff0c;每一个…...

在 CentOS 系统中,您可以使用多种工具来查看网络速度和流量

在 CentOS 系统中&#xff0c;您可以使用多种工具来查看网络速度和流量 在 CentOS 系统中&#xff0c;您可以使用多种工具来查看网络速度和流量1. 使用 iftop安装 iftop使用 iftop 2. 使用 nload安装 nload使用 nload 3. 使用 vnstat安装 vnstat初始化 vnstat查看流量 4. 使用 …...

分布式----Ceph部署

目录 一、存储基础 1.1 单机存储设备 1.2 单机存储的问题 1.3 商业存储解决方案 1.4 分布式存储&#xff08;软件定义的存储 SDS&#xff09; 1.5 分布式存储的类型 二、Ceph 简介 三、Ceph 优势 四、Ceph 架构 五、Ceph 核心组件 #Pool中数据保存方式支持两种类型&…...

使用 PyTorch 实现 AlexNet 进行 MNIST 图像分类

AlexNet 是一种经典的深度学习模型&#xff0c;它在 2012 年的 ImageNet 图像分类比赛中大放异彩&#xff0c;彻底改变了计算机视觉领域的格局。AlexNet 的核心创新包括使用深度卷积神经网络&#xff08;CNN&#xff09;来处理图像&#xff0c;并采用了多个先进的技术如 ReLU 激…...

Python爬虫项目 | 一、网易云音乐热歌榜歌曲

文章目录 1.文章概要1.1 实现方法1.2 实现代码1.3 最终效果 2.具体讲解2.1 使用的Python库2.2 代码说明2.2.1 创建目录保存文件2.2.2 爬取网易云音乐热歌榜单歌曲 2.3 过程展示 3 总结 1.文章概要 学习Python爬虫知识&#xff0c;实现简单的一个小案例&#xff0c;网易云音乐热…...

【Linux】HTTP协议和HTTPS加密

文章目录 HTTP1、概念2、认识URL3、协议格式、请求方法和状态码4、HTTP请求和响应报头5、Cookie和Session HTTPS1、对称和非对称加密2、对称非对称加密安全分析3、证书 HTTP 1、概念 我们在应用层定制协议时&#xff0c;不建议直接发送结构体对象&#xff0c;因为在不同的环境…...

Linux编辑/etc/fstab文件不当,不使用快照;进入救援模式

目录 红帽镜像9救援模式 现象 解决 第一步&#xff1a;修改启动参数以进入救援模式 第二步&#xff1a;进入救援模式、获取root权限、编辑/etc/fstab文件 第三步&#xff1a;编辑好后在重启 下面是ai给的模板 红帽镜像9救援模式 编辑/etc/fstab不当时 17 /dev/nvme0n3p1…...

ubuntu升级postgres

已经有了postgres12&#xff0c;记录一下升级从postgres12升级到15的过程及遇到的一些问题&#xff0c;我没有备份&#xff0c;单纯升级 1、升级过程 深色版本 sudo systemctl stop postgresql 升级PostgreSQL 停止PostgreSQL服务&#xff1a; 停止当前版本的PostgreSQL服务…...

vue2在el-dialog打开的时候使该el-dialog中的某个输入框获得焦点方法总结

在 Vue 2 中&#xff0c;如果你想通过 ref 调用一个方法&#xff08;如 inputFocus&#xff09;来聚焦一个输入框&#xff0c;确保以下几点&#xff1a; 确保 ref 的设置正确&#xff1a;你需要确保在模板中正确设置了 ref&#xff0c;并且它指向了你想要操作的组件或 DOM 元素…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

快刀集(1): 一刀斩断视频片头广告

一刀流&#xff1a;用一个简单脚本&#xff0c;秒杀视频片头广告&#xff0c;还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农&#xff0c;平时写代码之余看看电影、补补片&#xff0c;是再正常不过的事。 电影嘛&#xff0c;要沉浸&#xff0c;…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...