SpringBoot日常:基于DeferredResult的异步处理

news2024/9/24 23:32:58

文章目录

    • 示例代码
    • 代码执行结果
    • 代码执行过程解析
    • DeferredResult 的优势

本章内容主要讲讲基于DeferredResult的异步处理

在 Servlet 容器中启用了异步请求处理功能,控制器方法就可以用 包装任何支持的控制器方法返回值DeferredResult,控制器可以从不同的线程异步产生返回值 — — 例如,响应外部事件(JMS 消息)、计划任务或其他事件

简单的讲述整个异步逻辑,就是一个请求过来,以往tomcat会从自身容器取出一个线程去执行逻辑,这个容器线程在逻辑没处理完之前,一直处于阻塞状态,其他请求进来也无法使用。使用本章介绍的DeferredResult后,若业务中有自定义线程池去处理逻辑,那tomcat的容器线程则可以释放,逻辑处理完回来会根据保存的上下文将结果写回到请求中去

同步阻塞:
在这里插入图片描述
异步非阻塞:
在这里插入图片描述

示例代码

@Configuration
@EnableAsync
public class AsyncConfig {

    private int corePoolSize = 16;
    
    private int maxPoolSize = 90;
    
    private int queueCapacity = 2000;

	//指定当前线程池为主线程池
    @Bean("taskExecutor")
    @Primary 
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(corePoolSize);
        taskExecutor.setMaxPoolSize(maxPoolSize);
        taskExecutor.setQueueCapacity(queueCapacity);
        taskExecutor.setKeepAliveSeconds(60);
        // 拒绝策略-抛异常
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        taskExecutor.setThreadGroupName("Task-");
        taskExecutor.setThreadNamePrefix("common-");
        taskExecutor.setBeanName("taskExecutor");
        return taskExecutor;
    }
}


@RestController
@RequestMapping("/mytest")
public class AsyncController {

	@Autowired
    private TaskExecutor taskExecutor;

	@GetMapping("/async")
    public DeferredResult<Integer> async() {
        System.out.println("当前线程 外部 " + Thread.currentThread().getName());
        DeferredResult<Integer> result = new DeferredResult<>();
        CompletableFuture.supplyAsync(this::count,taskExecutor)
                .whenCompleteAsync((res, throwable) -> {
                    if (throwable != null) {
                        result.setErrorResult(throwable.getMessage());
                    }else{
                        result.setResult(res);
                    }
                });

        return result;
    }

	private Integer count() {
        System.out.println("内部线程 名称 "+Thread.currentThread().getName());
        System.out.println("-------start---------------");
        int count = 0;
        for (int i = 0; i < 1000000; i++) {
            for (int j = 0; j < 10000; j++) {
                count = count + j;
            }
        }
        System.out.println("-------end---------------");
        return count;
    }
}

代码执行结果

在这里插入图片描述

代码执行过程解析

上述代码我们创建了一个业务线程池taskExecutor,然后controller方法在async DeferredResult内创建了一个DeferredResult对象,接着使用CompletableFuture向业务线程池taskExecutor提交我们的请求处理逻辑(其内部处理完毕后把结果设置到创建的DeferredResult),最后返回创建的DeferredResult对象。其整个处理过程如下:

1)Tomcat容器接收路径为personDeferredResult的请求后,会分配一个容器线程来执行DispatcherServlet进行请求分派,请求被分到含有/async路径的controller,然后执行async方法,该方法内创建了一个DeferredResult对象,接着把处理任务提交到了线程池进行处理,最后返回DeferredResult对象。

2)Spring MVC内部在/async方法返回后会保存DeferredResult对象到内存队列或者列表,然后会调用request.startAsync()开启异步处理,并且调用DeferredResult对象的setResultHandler方法,设置当异步结果产生后对结果进行重新路由的回调函数(逻辑在WebAsyncManager的startDeferredResultProcessing方法),接着释放分配给当前请求的容器线程,与此同时当前请求的DispatcherServlet和所有filters也执行完毕了,但是response流还是保持打开(因为任务执行结果还没写回)。

3)最终在业务线程池中执行的异步任务会产生一个结果,该结果会被设置到DeferredResult对象,然后设置的回调函数会被调用,接着Spring MVC会分派请求结果回到Servlet容器继续完成处理,DispatcherServlet被再次调用,使用返回的异步结果继续进行处理,最终把响应结果写回请求方。

DeferredResult 的优势

使用 DeferredResult 实现异步请求处理肯定有一定的优势和好处,这里总结三点

  1. 资源利用率高
    通过将耗时操作放到异步线程中执行,可以避免主线程阻塞,提高系统的并发处理能力和资源利用率。

  2. 灵活性高
    DeferredResult 允许手动设置异步处理结果,可以在多个线程中执行操作,适用于复杂的异步处理场景。

  3. 超时和异常处理
    DeferredResult 提供了超时处理和异常处理机制,允许开发者定义超时和异常处理逻辑,提高了异步请求处理的可靠性和健壮性。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

谷粒商城实战笔记-261~262-商城业务-订单服务-页面环境搭建-SpringSession

文章目录 一&#xff0c;261-商城业务-订单服务-页面环境搭建1&#xff0c;静态资源上传2&#xff0c;配置域名映射3&#xff0c;网关配置4&#xff0c;页面静态资源引用修改 二&#xff0c;262-商城业务-订单服务-整合SpringSession1&#xff0c;页面跳转2&#xff0c;配置Spr…

Python实战:如何使用K-means算法进行餐馆满意度NLP情感分析

&#x1f34a;作者&#xff1a;计算机毕设匠心工作室 &#x1f34a;简介&#xff1a;毕业后就一直专业从事计算机软件程序开发&#xff0c;至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长&#xff1a;按照需求定制化开发项目…

详解Apache 和 Tomcat 整合原理及区别

Apache 和 Tomcat 都是Web服务器&#xff0c;它们之间既有联系又有区别。Apache主要负责静态解析&#xff0c;如HTML。Tomcat主要负责动态解析&#xff0c;如JSP。 为什么要让 Apache 与 Tomcat 之间进行连接呢? 原因有下面几个&#xff1a; 提升对静态文件的处理性能 利用…

ms_送给新人的面试题简单解答

第一部分 1 项目中遇到的bug或者难题 这个问题比较容易&#xff0c;每个人都会在开发过程中遇到或多或少的问题&#xff0c;你不可能答我已经天下无敌了&#xff0c;大家开发的项目类型都不太一样&#xff0c;事实上也没人听得太仔细&#xff0c;就算你要说的‘难题‘并不难&…

Apache Druid日志实时分析

业务分析 ​ 秒杀业务中&#xff0c;通常会有很多用户同时蜂拥而上去抢购热卖商品&#xff0c;经常会出现抢购人数远大于商品库存。其实在秒杀过程中&#xff0c;热卖商品并不多&#xff0c;几乎只占1%&#xff0c;而99%的流量都源自热卖商品&#xff0c;很有可能因为这1%的热…

【SQL】分类统计的薪水

目录 题目 分析 代码 题目 表: Accounts ------------------- | 列名 | 类型 | ------------------- | account_id | int | | income | int | ------------------- 在 SQL 中&#xff0c;account_id 是这个表的主键。 每一行都包含一个银行帐户的月收入的…

深入解析Go语言os/user包:用户和组管理实战指南

深入解析Go语言os/user包&#xff1a;用户和组管理实战指南 引言什么是os/user包&#xff1f;为什么要学习os/user包&#xff1f;本文将介绍的内容 os/user包基础如何导入os/user包获取当前用户信息示例代码 *user.User类型详解常见错误处理小结 用户查询与管理根据用户名查询用…

这本大模型书籍我敢说知道的人不超过1%,大模型入门必备书籍

当然可以&#xff01;我为您推荐一本关于大模型的书籍&#xff1a;《Transformer Tutorials: From Theory to Practice》。虽然这本书不是直接以“大模型”命名&#xff0c;但它涵盖了构建和理解大规模语言模型&#xff08;如GPT系列和BERT&#xff09;所需的关键技术和理论。接…

娱乐社交、游戏行业的最新玩法实践与未来增长趋势解读|网易数智x华为云城市沙龙杭州站邀你前来!

随着5G、AI、区块链等前沿技术的深度融合应用&#xff0c;泛娱乐行业正经历深刻变革的同时&#xff0c;也面临着一系列挑战与问题&#xff0c;面对社交产品监管的加强、海外市场的双重机遇与风险以及增速放缓的游戏行业...... 探求新增长点与新思路成为当下泛娱乐行业从业者的关…

收银系统源码助力零售门店数字化升级

一、国内零售业数字化转型迈入深水区 近年来&#xff0c;我国零售业数字化进程显著加速&#xff0c;从线上电商到新零售模式&#xff0c;再到利用大数据、人工智能等技术优化供应链、提升体验&#xff0c;每一步都见证了行业的深刻变革。随着零售行业进入存量市场竞争&#xf…

nuxt3连接mongodb操作

文章目录 创建一个nuxt3应用添加nuxt后端服务nuxt3路由创建mongo数据连接mongodb数据库补充添加显示(用v-for打印出数组)nuxt-server-insertmongodb删除数据创建一个nuxt3应用 Node.js - v18.0.0 或更新版本推荐使用 Visual Studio Code 以及 Volar 扩展npx nuxi@latest init p…

使用jwt实现登录验证

jwt工具类 public class JwtUtil {public static String key"mykey";public static String genToken(String username) {JWTCreator.Builder builder JWT.create();Map<String, Object> headersnew HashMap<>();headers.put("typ","jwt&…

uniapp重新编译在微信开发者工具跳转指定页面

uniapp重新编译在微信开发者工具跳转指定页面 步骤 选择编译模式添加编译模式设置启动页面

rk3588调用NPU、查看npu的使用情况

1、rk3588启用NPU 启用三个内核->RKNNLite.NPU_CORE_0_1_2 rknn_lite RKNNLite(verboseFalse) ret rknn_lite.load_rknn(RKNN_MODEL) ret rknn_lite.init_runtime(core_maskRKNNLite.NPU_CORE_0_1_2) 2、查看NPU使用情况&#xff1a; watch sudo cat /sys/kernel/deb…

LaViT:Less-Attention Vision Transformer的特性与优点

引言 https://arxiv.org/pdf/2406.00427 随着计算机视觉领域的发展&#xff0c;视觉Transformer&#xff08;ViTs&#xff09;逐渐成为一项重要技术。尽管ViTs在捕捉图像中的长距离依赖关系方面表现出色&#xff0c;但其沉重的计算负担和潜在的注意力饱和问题一直是实际应用的…

利用Python对Excel数据进行条件筛选与排序

目录 一、Python与Excel数据处理的基础知识 1.1 Python中的Excel数据处理库 1.2 pandas库简介 二、使用pandas读取Excel数据 三、Excel数据的条件筛选 3.1 单条件筛选 3.2 多条件筛选 3.3 使用query方法 四、Excel数据的排序 4.1 单列排序 4.2 多列排序 五、案例分…

Python自动化:Excel根据IP匹配网段获取所属源端口

需求 现在有两个文件&#xff1a; 1. 【NTP.xlsx】&#xff1a;有name、IP、fenzhihang、vendor、source这五列 2. 【IP.xlsx】&#xff1a;有daqu、fenzhihang、duankou、IP、mask、gateway、subnet、yongtu、miaoshu这九列 现在更新基线&#xff0c;每台设备都需要增加nt…

ET6框架(二)Demo工程的运行及编译

1.工程下载地下&#xff1a; GitHub - egametang/ET at release6.0 2.复制地址后下载&#xff0c;在本人使用时ET已更新到最新9.0的版本&#xff0c;因此下载后需要切换分支到6.0版本 3.下载完工程后可以用 UnityHub打开工程&#xff0c;如没有对应版本可以在&#xff1a;h…

OpenHarmony技术开发:Launcher架构应用启动流程分析

简介 Launcher 作为系统人机交互的首要入口&#xff0c;提供应用图标的显示、点击启动、卸载应用&#xff0c;并提供桌面布局设置以及最近任务管理等功能。 Launcher 采用 扩展的 TS 语言&#xff08;eTS&#xff09;开发&#xff0c;主要的结构如下&#xff1a; product 业务…

安卓13 背光调节非线性问题处理,调节范围不正常问题

总纲 android13 rom 开发总纲说明 目录 1.前言 2.问题分析 3.代码修改 4.彩蛋 1.前言 我们看看现在的版本的亮度图 2.问题分析 当背光亮度设置为0%时,每次按下亮度增加键或者 input keyevent BRIGHTNESS_UP,亮度UI的增幅较大,首次按下后亮度平滑提升至大约55%,随后继…