【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】

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Leecode刷题C语言之统计好节点的数目

执行结果:通过 执行用时和内存消耗如下&#xff1a; 题目&#xff1a;统计好节点的数目 现有一棵 无向 树&#xff0c;树中包含 n 个节点&#xff0c;按从 0 到 n - 1 标记。树的根节点是节点 0 。给你一个长度为 n - 1 的二维整数数组 edges&#xff0c;其中 edges[i] [ai,…

Cellebrite VS IOS18Rebooting

Cellebrite VS IOS18Rebooting我们想分享一些有关 iOS 18 重启“功能”的信息。在过去一周左右的时间里&#xff0c;人们对 iOS 18 中一项新的未记录功能产生了极大关注&#xff0c;该功能会导致设备在一段时间不活动后重新启动。 这意味着&#xff0c;如果设备在一定时间不活…

mysql每日一题(上升的温度,date数据的计算)

日期之间的运算 日期类型的加法运算 data_add(now_data,interval 1 month) select date_add(now(), interval 1 day); -- 加1天 select date_add(now(), interval 1 hour); -- 加1小时 select date_add(now(), interval 1 minute); -- 加1分钟 select date_add(now(), inter…

windows NGIMX配置WebSocket反向代理

linux下 据说nginx是要有 stream的模块 Linux安装Nginx步骤之后续&#xff0c;带stream模块-CSDN博客 Nginx从1.3.13版本就开始支持WebSocket linux 下参考如下链接 配置 Nginx 反向代理 WebSocket - 哈喽哈喽111111 - 博客园 (cnblogs.com) SSL的配置参考 【Linux】采用…

蓝桥杯竞赛单片机组备赛【经验帖】

本人获奖情况说明 笔者本人曾参加过两次蓝桥杯电子赛&#xff0c;在第十二届蓝桥杯大赛单片机设计与开发组获得省级一等奖和国家级二等奖&#xff0c;在第十五届嵌入式设计开发组获得省级二等奖。如果跟着本帖的流程备赛&#xff0c;只要认真勤奋&#xff0c;拿个省二绝对没问…

《鸿蒙生态:开发者的机遇与挑战》

一、引言 在当今科技飞速发展的时代&#xff0c;操作系统作为连接硬件与软件的核心枢纽&#xff0c;其重要性不言而喻。鸿蒙系统的出现&#xff0c;为开发者带来了新的机遇与挑战。本文将从开发者的角度出发&#xff0c;阐述对鸿蒙生态的认知和了解&#xff0c;分析鸿蒙生态的…

入侵检测算法平台部署LiteAIServer视频智能分析平台行人入侵检测算法:科技守护安全的新篇章

在现代化城市快速发展的背景下&#xff0c;安全防范已成为城市管理与社会生活中不可或缺的一环。随着人工智能、大数据、物联网等技术的飞速发展&#xff0c;智能化安防系统正逐步改变着传统的安全防护模式&#xff0c;特别是在行人入侵检测领域&#xff0c;视频智能分析平台Li…

【Linux】Linux 权限的理解

首先我们先介绍Linux中基本的用户认识&#xff1a; Linux下有两种用户&#xff1a;超级用户&#xff08;root&#xff09;和普通用户 超级用户&#xff1a;可以再linux系统下做任何事情&#xff0c;不受限制普通用户&#xff1a;在linux下做有限(权限较低)的事情。超级用户的…

给阿里云OSS绑定域名并启用SSL

为什么要这么做&#xff1f; 问题描述&#xff1a; 当用户通过 OSS 域名访问文件时&#xff0c;OSS 会在响应头中增加 Content-Disposition: attachment 和 x-oss-force-download: true&#xff0c;导致文件被强制下载而不是预览。这个问题特别影响在 2022/10/09 之后新开通 OS…

spring boot整合https协议

整体目录 1. 生成SSL证书 首先&#xff0c;使用keytool生成一个自签名证书。打开命令行工具并运行以下命令&#xff1a; keytool -genkeypair -alias myserver -keyalg RSA -keysize 2048 -keystore keystore.jks -validity 365 这将创建一个名为keystore.jks的文件&#xf…

【Window主机访问Ubuntu从机——Xrdp配置与使用】

使用Xrdp在Window环境下远程桌面访问Ubuntu主机 文章目录 Ubuntu安装图形化界面Ubuntu安装Xrdp通过网线连接两台主机Window主机有线连接配置Ubuntu从机设置测试有线连接 Window主机打开远程桌面功能参考文章总结 Ubuntu安装图形化界面 sudo apt update sudo apt upgrade sudo …

游戏引擎学习第10天

视频参考:https://www.bilibili.com/video/BV1LyU3YpEam/ 介绍intel architecture reference manual 地址:https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html RDTS&#xff08;读取时间戳计数器&#xff09;指令是 x86/x86_64 架构中的…

计算机网络(11)和流量控制补充

这一篇对数据链路层中的和流量控制进行详细学习 流量控制&#xff08;Flow Control&#xff09;是计算机网络中确保数据流平稳传输的技术&#xff0c;旨在防止数据发送方发送过多数据&#xff0c;导致接收方的缓冲区溢出&#xff0c;进而造成数据丢失或传输失败。流量控制通常…

PVE纵览-安装系统卡“Loading Driver”的快速解决方案

PVE纵览-安装系统卡“Loading Driver”的快速解决方案 文章目录 PVE纵览-安装系统卡“Loading Driver”的快速解决方案摘要通过引导参数解决PVE安装卡在“Loading Driver”问题官方解决方法 关键字&#xff1a; PVE、 显卡、 Loading、 Driver、 nomodeset 摘要 在虚拟机…

Docker在CentOS上的安装与配置

前言 随着云计算和微服务架构的兴起&#xff0c;Docker作为一种轻量级的容器技术&#xff0c;已经成为现代软件开发和运维中的重要工具。本文旨在为初学者提供一份详尽的指南&#xff0c;帮助他们在CentOS系统上安装和配置Docker及相关组件&#xff0c;如Docker Compose和私有…

在 Oracle Linux 8.9 上安装Oracle Database 23ai 23.5

在 Oracle Linux 8.9 上安装Oracle Database 23ai 23.5 1. 安装 Oracle Database 23ai2. 连接 Oracle Database 23c3. 重启启动后&#xff0c;手动启动数据库4. 重启启动后&#xff0c;手动启动 Listener5. 手动启动 Pluggable Database6. 自动启动 Pluggable Database7. 设置开…

实验6记录网络与故障排除

实验6记录网络与故障排除 实验目的及要求&#xff1a; 通过实验&#xff0c;掌握如何利用文档记录网络设备相关信息并完成网络拓扑结构的绘制。能够使用各种技术和工具来找出连通性问题&#xff0c;使用文档来指导故障排除工作&#xff0c;确定具体的网络问题&#xff0c;实施…

Go开发指南- Goroutine

目录&#xff1a; (1)Go开发指南-Hello World (2)Go开发指南-Gin与Web开发 (3)Go开发指南-Goroutine Goroutine 在java中我们要实现并发编程的时候&#xff0c;通常要自己维护一个线程池&#xff0c;并且需要去包装任务、调度任务和维护上下文切换。这个过程需要消耗大量的精…

解决failed to execute PosixPath(‘dot‘) 或者GraphViz‘s executables not found

在网上找了很多方法都没解决&#xff0c;所以写一篇文章帮助和我遇到同样问题的人 解决方法&#xff1a; 因为python解释器会解释转移字符&#xff0c;因此在环境变量中把\bin换成\\bin即可 解决过程&#xff1a; 系统&#xff1a;win10 已安装pip install graphviz&#xff0…

力扣 LeetCode 541. 反转字符串II(Day4:字符串)

解题思路&#xff1a; i可以成段成段的跳&#xff0c;而不是简单的i class Solution {public String reverseStr(String s, int k) {char[] ch s.toCharArray();// 1. 每隔 2k 个字符的前 k 个字符进行反转for (int i 0; i < ch.length; i 2 * k) {// 2. 剩余字符小于 …