CompletableFuture生产中使用问题

CompletableFuture生产中使用问题

    • 1 背景
    • 2 测试
    • 3 原因
    • 4. 总结

1 背景

接到一个任务,需要优化下单接口,查看完业务逻辑后发现有一些可以并行或异步查询的地方,于是采用CompletableFuture来做异步优化,提高接口响应速度,伪代码如下

//查询用户信息CompletableFuture<JSONObject> userInfoFuture = CompletableFuture.supplyAsync(() -> proMemberService.queryUserById(ordOrder.getId()));//查询积分商品信息CompletableFuture<JSONObject> integralProInfoFuture = CompletableFuture.supplyAsync(() -> proInfoService.getProById(ordOrderIntegral.getProId()));//查询会员积分信息CompletableFuture<Integer> integerFuture = CompletableFuture.supplyAsync(() -> proMemberService.getTotalIntegralById(ordOrder.getOpenId()));

2 测试

优化完后,测试执行速度2000ms下降到600ms,经过本地和测试环境测试后,上线生产,
生产日志打印出来的线程号,却不是从CompletableFuture的默认线程池中取出的.
生产日志
在这里插入图片描述

本地和测试环境打印日志
在这里插入图片描述
日志中发现生产环境为每个线程创建了一个全新的线程,如果并发太高,会存在线程资源被耗尽的可能性,从而导致服务器崩溃.

3 原因

翻阅CompletableFuture的源码后,终于找到了原因: 是否使用默认ForkJoinPool线程池和机器配置有关.

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {return asyncSupplyStage(ASYNC_POOL, supplier);}

点击进入asynPool

//是否使用默认线程池的判断依据
private static final Executor ASYNC_POOL = USE_COMMON_POOL ?ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();//useCommonPool的来源
private static final boolean USE_COMMON_POOL =(ForkJoinPool.getCommonPoolParallelism() > 1);

CompletableFuture是否使用默认线程池,是根据这个useCommonPool值来判断的,值为true使用

public static int getCommonPoolParallelism() {return COMMON_PARALLELISM;}public ForkJoinPool() {this(Math.min(MAX_CAP, Runtime.getRuntime().availableProcessors()),defaultForkJoinWorkerThreadFactory, null, false,0, MAX_CAP, 1, null, DEFAULT_KEEPALIVE, TimeUnit.MILLISECONDS);}public ForkJoinPool(int parallelism,ForkJoinWorkerThreadFactory factory,UncaughtExceptionHandler handler,boolean asyncMode,int corePoolSize,int maximumPoolSize,int minimumRunnable,Predicate<? super ForkJoinPool> saturate,long keepAliveTime,TimeUnit unit) {checkPermission();int p = parallelism;if (p <= 0 || p > MAX_CAP || p > maximumPoolSize || keepAliveTime <= 0L)throw new IllegalArgumentException();if (factory == null || unit == null)throw new NullPointerException();this.factory = factory;this.ueh = handler;this.saturate = saturate;this.keepAlive = Math.max(unit.toMillis(keepAliveTime), TIMEOUT_SLOP);int size = 1 << (33 - Integer.numberOfLeadingZeros(p - 1));int corep = Math.min(Math.max(corePoolSize, p), MAX_CAP);int maxSpares = Math.min(maximumPoolSize, MAX_CAP) - p;int minAvail = Math.min(Math.max(minimumRunnable, 0), MAX_CAP);this.bounds = ((minAvail - p) & SMASK) | (maxSpares << SWIDTH);this.mode = p | (asyncMode ? FIFO : 0);this.ctl = ((((long)(-corep) << TC_SHIFT) & TC_MASK) |(((long)(-p)     << RC_SHIFT) & RC_MASK));this.registrationLock = new ReentrantLock();this.queues = new WorkQueue[size];String pid = Integer.toString(getAndAddPoolIds(1) + 1);this.workerNamePrefix = "ForkJoinPool-" + pid + "-worker-";}

4. 总结

  • 使用CompletableFuture一定要自定义线程池
  • CompletableFuture是否使用默认线程池和机器核心数有关,核心数减1大于1才会使用默认线程池,否则为每个任务创建一个线程.
  • 即使服务器核心大于2使用默认线程池也可能会因为线程池中线程过少,导致线程大量等待,降低吞吐率,甚至拖垮服务器
  • ForkJoinPool使用于CPU密集型的任务(计算).

线程池大小与处理器的利用率之比可以使用下面的公式进行估算公式:
N threads = N CPU * U CPU * (1 + W/C)
其中:

  • NCPU 是处理器的核的数目,可以通过 Runtime.getRuntime().availableProce-
    ssors() 得到

  • U CPU 是期望的CPU利用率(该值应该介于0和1之间)

  • W/C是等待时间与计算时间的比率

一般的设置线程池的大小规则是:

  • 如果服务是cpu密集型的,设置为电脑的核数

  • 如果服务是io密集型的,设置为电脑的核数*2

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

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

相关文章

安全测试国家标准解读——数据库管理和文件管理

下面的系列文章主要围绕《GB/T 38674—2020 信息安全技术 应用软件安全编程指南》进行讲解&#xff0c;该标准是2020年4月28日&#xff0c;由国家市场监督管理总局、国家标准化管理委员会发布&#xff0c;2020年11月01日开始实施。我们对该标准中一些常见的漏洞进行了梳理&…

环境搭建-Ubuntu20.04.6系统TensorFlow BenchMark的GPU测试

1. 下载Ubuntu20.04.6镜像 登录阿里云官方镜像站&#xff1a;阿里巴巴开源镜像站-OPSX镜像站-阿里云开发者社区 2. 测试环境 Server OS&#xff1a;Ubuntu 20.04.6 LTS Kernel: Linux 5.4.0-155-generic x86-64 Docker Version&#xff1a;24.0.5, build ced0996 docker-com…

Django框架:使用channels实现websocket,配置和项目实际使用

一、基本配置 依赖包&#xff1a; Django3.2 django-cors-headers3.5.0 redis4.6.0 #操作redis数据库的 channels3.0.0 #websocket channels-redis4.1.0 #通道层需要&#xff0c;依赖redis包项目目录结构&#xff1a; study_websocket --study_websocket --__init__.py --s…

3dsmax制作一个机器人

文章目录 建模身子&#xff1a;眼睛&#xff1a;头饰&#xff1a;肩膀手臂腿调整细节 渲染导出objMarmoset Toolbag 3.08渲染给眼睛添加材质&#xff0c;设置为自发光添加背景灯光 建模 身子&#xff1a; 眼睛&#xff1a; 头饰&#xff1a; 肩膀 手臂 腿 调整细节 渲染 导出…

Android性能优化之游戏引擎初始化ANR

近期&#xff0c;着手对bugly上的anr 处理&#xff0c;记录下优化的方向。 借用网上的一张图&#xff1a; 这里的anr 问题是属于主线程的call 耗时操作。需要使用trace 来获取发生anr前一些列的耗时方法调用时间&#xff0c;再次梳理业务&#xff0c;才可能解决。 问题1 ja…

【Linux进程】进程控制(下) {进程程序替换:程序替换的工作原理,程序替换函数exec*,简单的命令行解释器}

四、进程程序替换 之前用fork创建子进程后&#xff0c;父子进程执行同一个程序的不同代码段。 如何使子进程执行另一个不同的程序呢&#xff1f;子进程需要进行程序替换&#xff01; 程序替换&#xff0c;就是通过特定的接口&#xff0c;将磁盘上一个全新的程序&#xff08;包…

❤ Win7 电脑的使用

❤ Win7 电脑的使用 日常使用 1、 电脑显示文件的后缀名 开发使用 1、win7启动Vue项目 新版本的node.js已经不支持win7操作系统&#xff0c;其最多只能用node.js的v13.14.0。所以安装vue/cli时不能安装最新版&#xff0c;得装指定版本 下载安装node.js 因为Win7系统最多…

Python Web开发技巧VII

目录 装饰器inject_serializer 装饰器atomic rebase git 清理add的数据 查看git的当前工作目录 makemigrations文件名称 action(detailTrue, methods["GET"]) 如何只取序列化器的一个字段进行返回 Response和JsonResponse有什么区别 序列化器填表和单字段如…

数学建模-蒙特卡洛模拟

%% 蒙特卡罗用于模拟三门问题 clear;clc %% &#xff08;1&#xff09;预备知识 % randi([a,b],m,n)函数可在指定区间[a,b]内随机取出大小为m*n的整数矩阵 randi([1,5],5,8) %在区间[1,5]内随机取出大小为5*8的整数矩阵 % 2 5 4 5 3 1 4 2 %…

(无人机方向)ros小白之键盘控制无人机(终端方式)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一&#xff1a;配置pycharm的ros开发环境二&#xff1a;核心代码讲解三 效果演示XTDrone 四 完整代码 前言 ubuntu 18.04 pycharm ros melodic 做一个在终端中…

微信小程序——同一控件的点击与长按事件共存的解决方案

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

植物一区HR | 植物生理组+转录组:揭示豆科植物响应干旱胁迫机制

PlantArray 植物高通量生理学表型监测系统 是一套以植物生理学为基础的高精度&#xff0c;高通量&#xff0c;自动化表型监测系统&#xff0c;集合实验设置、数据分析、决策工具于一身&#xff0c;能够高通量实时动态监测并进行全天候生理及环境参数采集&#xff0c;是进行植物…

网络设备中的配置文件管理

建立强大网络的第一步是为灾难和网络中断做好准备&#xff0c;许多企业在中断期间遭受损失&#xff0c;因为他们缺乏备份计划并且配置管理不达标&#xff0c;使用配置文件管理工具进行适当的配置文件管理不仅有助于处理网络中断&#xff0c;还有助于优化网络性能。 使用配置文…

海尔设计借助亚马逊云科技生成式AI,实现端到端的云上工业设计解决方案

海尔创新设计中心&#xff08;以下简称海尔设计&#xff09;成立于1994年&#xff0c;目前拥有400多名设计师&#xff0c;为海尔智家旗下七大品牌全球的所有产品提供设计创新和模式探索。亚马逊云科技为海尔设计提供了四个完整的云上解决方案&#xff0c;全面替代自有机房&…

Vue3 word如何转成pdf代码实现

&#x1f642;博主&#xff1a;锅盖哒 &#x1f642;文章核心&#xff1a;word如何转换pdf 目录 1.前端部分 2.后端部分 在Vue 3中&#xff0c;前端无法直接将Word文档转换为PDF&#xff0c;因为Word文档的解析和PDF的生成通常需要在后端进行。但是&#xff0c;你可以通过Vu…

HCIA 第二课总结

配置网络设备的明文密钥实验组网 实验拓扑 将一个路由器使用配置口进行连接 sys #进入系统视图模式 sysname RTA #给设备命名 user-interface console 0 #进入用户接口配置界面 authentication-mode password #配置认证模式为密钥认证 set authentication password ciphe…

百题千解计划【CSDN每日一练】订班服(附解析+多种实现方法:Python、Java、C、C++、C#、Go、JavaScript)

如果决意去做一件事了,就不要再问自己和别人值不值得,心甘情愿才能理所当然,理所当然才会义无反顾。 🎯作者主页: 追光者♂🔥 🌸个人简介: 💖[1] 计算机专业硕士研究生💖 🌟[2] 2022年度博客之星人工智能领域TOP4🌟 🏅[3] 阿里云社区特邀专…

LeetCode刷题笔记-287题寻找重复数

LeetCode 287 寻找重复数 难度&#xff1a;中等 题目&#xff1a; 给定一个包含 n 1 个整数的数组 nums &#xff0c;其数字都在 [1, n] 范围内&#xff08;包括 1 和 n&#xff09;&#xff0c;可知至少存在一个重复的整数。 假设 nums 只有 一个重复的整数 &#xff0c;返回…

软件外包开发测试管理工具

测试是软件工程中非常重要的一个环节&#xff0c;在上线前必须需要经过严格的测试才能确保上线后软件系统长时间运行。有大量的软件开发和测试管理工具&#xff0c;每一个工具都有自己的特点&#xff0c;今天和大家分享一些常见的工具&#xff0c;希望对大家有所帮助。北京木奇…

【Spring Boot丨序列化、反序列化】

序列化、反序列化 概述Jackson 序列化和反序列化简介自定义序列化器注册外部序列化程序&#xff1a; 指定类的 Json 序列化、反序列化 主页传送门&#xff1a;&#x1f4c0; 传送 概述 序列化是将对象转换为字节序列的过程&#xff0c;而反序列化则是将字节序列恢复为对象的过…