您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

你是如何评估一个线程池需要设置多少个线程

时间:2021-03-31 12:05:55  来源:今日头条  作者:中间件兴趣圈

见字如面,我是威哥,一个从普通二本院校毕业,从未曾接触分布式、微服务、高并发到通过技术分享实现职场蜕变,成长为RocketMQ社区优秀布道师、大厂资深架构师,出版《RocketMQ技术内幕》一书,欢迎大家关注我,一起交流进步

JAVA并发编程是大厂第一轮面试中的高频面试题,而线程池又是其中的典型代表,本文将梳理关于线程池的工作机制,并提出灵魂之问:你对线程池的工作机制这么了解,那你在工作中是如何判断一个线程池需要创建多少个线程的呢?

1、线程池基本工作原理与面试指南


1.1 java线程池的核心属性

JAVA 线程池的核心属性如下:

  • int corePoolSize
    核心线程数
  • int maximumPoolSize
    线程池最大线程数
  • long keepAliveTime
    线程保持活跃的时间
  • TimeUnit unit
    keepAliveTime 的时间单位
  • BlockingQueue< Runnable > workQueue
    任务挤压队列
  • ThreadFactory threadFactory
    线程创建工厂类
  • RejectedExecutionHandler handler
    拒绝策略

1.2 向线程池提交任务时线程创建过程

那当用户向线程池提交一个任务的时候,线程池会如何创建线程呢?

  1. 首先线程池会判断当前已创建的线程是否小于 corePoolSize (核心线程数),如果小于,则无论已创建的线程是否空闲,都会选择创建一个新的线程来执行该任务,直到已创建的线程等于核心线程数
  2. 当线程池中已创建的线程数等于核心核心线程数时,用户继续向线程池提交任务时,此时会先判断任务队列是否已满:
    1)如果任务队列未满,则将任务放入队列中。2)如果任务队列已满,则判断当前线程数量是否超过了最大线程数量,如果未超过,则创建一个新的线程来执行该任务,如果线程池已创建的线程数量等最大线程数,则执行拒绝策略。

 温馨提示:所以如果线程池使用的队列无界队列,最大线程数会变得没有意义。

1.3 线程池的拒绝策略、使用场景

JUC 默认提供了如下拒绝策略:

  • AbortPolicy
    拒绝,直接抛出 RejectedExecutionException,默认值。
  • CallerRunsPolicy
    由调用线程直接运行任务的 run 方法,即异步转同步。
  • DiscardOldestPolicy
    丢弃任务队列中最先进入的任务。
  • DiscardPolicy
    拒绝了,就不执行,“当没事人事”样。

拒绝策略触发的条件:线程池使用的是有界任务队列时,才有可能被触发,当队列已满,并且线程池创建的线程已经达到了最大允许的线程池时。

默认情况下,通常使用 AbortPolicy 即可

CallerRunsPolicy 异步转同步在出现拒绝的情况下其实意义不大,没有想出其合适的场景,因为需要执行拒绝策略的时候,已经处理变慢了,再同步执行任务,只会增加服务器的负载,不利于恢复问题。

DiscardOldestPolicy 这种策略,通常用于类似记录轨迹,偶尔丢失点数据没关系,但希望最新的数据能得到保存。

DiscardPolicy 策略,通常用来异步打印日志,直接忽略不执行,期望保存旧的数据。

1.4 如何选择阻塞队列

阿里内部的开源规范明确禁止使用无界队列,如果使用无界队列,任务会不受限制的往线程池中提交,有可能造成内存溢出。

如果使用无界队列,最大线程数这个参数将会失效,因为永远也不会创建多于核心线程数量的线程。

1.5 线程池工厂有何实际用处

ThreadFactory threadFactory,线程池工厂,在使用线程池时,强烈推荐使用自己定义的线程工厂,这样能为线程池中的线程进行命名,方便跟大家使用 jsatck 命令查看线程栈时,能快速识别对应的线程。

1.6 keepAliveTime参数的作用

keepAliveTime :通俗点来说,这个参数表示线程的最大空闲时间,即如果线程没有在执行任务,能存活的时间。

默认情况下,该参数只针对超过核心线程数(corePoolSize) 的线程,可通过将allowCoreThreadTimeOut设置为true,则核心线程数也会因为空闲而被关闭。

2、如何为一个线程池设置合适的线程数量


目前根据我看过的一些开源框架,设置多少个线程数量通常是根据应用的类型:IO密集型、CPU密集型。

  • IO密集型通常设置为2n+1,其中n为CPU核数
  • CPU密集型通常设置为 n+1。

实际情况往往复杂得多,并不会按照这个进行设置,上面的公司通常适合框架设置IO线程的个数,例如netty,dubbo这种底层通讯框架通常会参考上述标准进行设置。

关于在实际业务开发中,如何为一个线程池设置合适的线程呢?

其实对于IO密集型类型的应用,网上还有一个公式:线程数 = CPU核心数/(1-阻塞系数)

引入了阻塞系数的概念,一般为0.8~0.9之间,

在我们的业务开发中,基本上都是IO密集型,因为往往都会去操作数据库,访问redis,es等存储型组件,都会涉及到磁盘IO,网络IO。

那什么场景下是CPU密集型呢?纯计算类,例如计算圆周率的位数,当然我们基本接触不到。

IO密集型,可以考虑多设置一些线程,主要目的是可以增加IO的并发度,CPU密集型不宜设置过多线程,因为是会造成线程切换,反而损耗性能。

接下来我们以一个实际的场景来说明如何设置线程数量。

一个4C8G的机器上部署了一个MQ消费者,在RocketMQ的实现中,消费端也是用一个线程池来消费线程的,那这个线程数要怎么设置呢?

如果按照 2n + 1 的公式,线程数设置为 9个,但在我们实践过程中发现如果增大线程数量,会显著提高消息的处理能力,说明 2n + 1 对于业务场景来说,并不太合适。

如果套用 线程数 = CPU核心数/(1-阻塞系数) 阻塞系数取 0.8 ,线程数为 20 。阻塞系数取 0.9,大概线程数40,20个线程数我觉得可以

如果我们发现数据库的操作耗时比较多,此时可以继续提高阻塞系数,从而增大线程数量。

那我们怎么判断需要增加更多线程呢?可以用jstack命令查看一下进程的线程栈,如果发现线程池中大部分线程都处于等待获取任务,则说明线程够用,如下图所示:

面试官:你是如何评估一个线程池需要设置多少个线程

 

如果大部分线程都处于运行状态,可以继续适当调高线程数量。

本期就介绍到这里了,希望对你有所帮助,同时也希望一键三连,给作者一些鼓励。

分享笔者关于RocketMQ线上故障案例剖析的电子书,私信回复RMQPDF即可获取。

面试官:你是如何评估一个线程池需要设置多少个线程


Tags:线程池   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
原文链接: https://mp.weixin.qq.com/s/MTw7z6n_wk4y4CTmGkoRoA一切要从CPU说起你可能会有疑问,讲多线程为什么要从CPU说起呢?原因很简单,在这里没有那些时髦的概念,你可以更加清...【详细内容】
2021-08-13  Tags: 线程池  点击:(96)  评论:(0)  加入收藏
多线程并发是Java语言中非常重要的一块内容,同时,也是Java基础的一个难点。说它重要是因为多线程是日常开发中频繁用到的知识,说它难是因为多线程并发涉及到的知识点非常之多,想...【详细内容】
2021-07-12  Tags: 线程池  点击:(110)  评论:(0)  加入收藏
1. Dubbo简介及线程池策略Apache Dubbo 是一款高性能、轻量级的开源 Java 服务框架。提供了六大核心能力:面向接口代理的高性能RPC调用,智能容错和负载均衡,服务自动注册和发现...【详细内容】
2021-05-18  Tags: 线程池  点击:(202)  评论:(0)  加入收藏
在上一篇文章C++使用socket实现与微信小程序通信(下)中,小懵白就给大家简要地讲解了线程池的原理。 今天呢,小懵白就给大家继续讲解C++如何实现封装线程池类。第一步首先,我们需...【详细内容】
2021-05-14  Tags: 线程池  点击:(204)  评论:(0)  加入收藏
见字如面,我是威哥,一个从普通二本院校毕业,从未曾接触分布式、微服务、高并发到通过技术分享实现职场蜕变,成长为RocketMQ社区优秀布道师、大厂资深架构师,出版《RocketMQ技...【详细内容】
2021-03-31  Tags: 线程池  点击:(277)  评论:(0)  加入收藏
作者公众号:一角钱技术(org_yijiaoqian)前言线程池的具体实现有两种,分别是ThreadPoolExecutor 默认线程池和ScheduledThreadPoolExecutor 定时线程池,上一篇已经分析过ThreadPoo...【详细内容】
2020-12-22  Tags: 线程池  点击:(143)  评论:(0)  加入收藏
之前我们介绍了线程池的四种拒绝策略,了解了线程池参数的含义,那么今天我们来聊聊Java 中常见的几种线程池,以及在jdk7 加入的 ForkJoin 新型线程池 首先我们列出Java 中的...【详细内容】
2020-11-05  Tags: 线程池  点击:(91)  评论:(0)  加入收藏
前面几篇文章分析了线程的主要实现,今天来整体总结以下他们。总览图直接上总结的总览图,如下图: 如果看过前几篇文章应该基本能够看懂这张总结图,可能在单独的一篇文章里弄懂了...【详细内容】
2020-09-08  Tags: 线程池  点击:(63)  评论:(0)  加入收藏
大多数线程池实现都离不开锁的使用,如互斥量pthread_mutex*结合条件变量pthread_cond*。众所周知,锁的使用对于程序性能影响较大,虽然现有的pthread_mutex*在锁的申请与释放方...【详细内容】
2020-08-24  Tags: 线程池  点击:(87)  评论:(0)  加入收藏
作为 Java 程序员,无论是技术面试、项目研发或者是学习框架源码,不彻底掌握 Java 多线程的知识,做不到心中有数,干啥都没底气,尤其是技术深究时往往略显发憷。坐稳扶好,通过今天的...【详细内容】
2020-08-12  Tags: 线程池  点击:(48)  评论:(0)  加入收藏
▌简易百科推荐
摘 要 (OF作品展示)OF之前介绍了用python实现数据可视化、数据分析及一些小项目,但基本都是后端的知识。想要做一个好看的可视化大屏,我们还要学一些前端的知识(vue),网上有很多比...【详细内容】
2021-12-27  项目与数据管理    Tags:Vue   点击:(1)  评论:(0)  加入收藏
程序是如何被执行的&emsp;&emsp;程序是如何被执行的?许多开发者可能也没法回答这个问题,大多数人更注重的是如何编写程序,却不会太注意编写好的程序是如何被运行,这并不是一个好...【详细内容】
2021-12-23  IT学习日记    Tags:程序   点击:(9)  评论:(0)  加入收藏
阅读收获✔️1. 了解单点登录实现原理✔️2. 掌握快速使用xxl-sso接入单点登录功能一、早期的多系统登录解决方案 单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器...【详细内容】
2021-12-23  程序yuan    Tags:单点登录(   点击:(8)  评论:(0)  加入收藏
下载Eclipse RCP IDE如果你电脑上还没有安装Eclipse,那么请到这里下载对应版本的软件进行安装。具体的安装步骤就不在这赘述了。创建第一个标准Eclipse RCP应用(总共分为六步)1...【详细内容】
2021-12-22  阿福ChrisYuan    Tags:RCP应用   点击:(7)  评论:(0)  加入收藏
今天想简单聊一聊 Token 的 Value Capture,就是币的价值问题。首先说明啊,这个话题包含的内容非常之光,Token 的经济学设计也可以包含诸多问题,所以几乎不可能把这个问题说的清...【详细内容】
2021-12-21  唐少华TSH    Tags:Token   点击:(9)  评论:(0)  加入收藏
实现效果:假如有10条数据,分组展示,默认在当前页面展示4个,点击换一批,从第5个开始继续展示,到最后一组,再重新返回到第一组 data() { return { qList: [], //处理后...【详细内容】
2021-12-17  Mason程    Tags:VUE   点击:(14)  评论:(0)  加入收藏
什么是性能调优?(what) 为什么需要性能调优?(why) 什么时候需要性能调优?(when) 什么地方需要性能调优?(where) 什么时候来进行性能调优?(who) 怎么样进行性能调优?(How) 硬件配...【详细内容】
2021-12-16  软件测试小p    Tags:性能调优   点击:(19)  评论:(0)  加入收藏
Tasker 是一款适用于 Android 设备的高级自动化应用,它可以通过脚本让重复性的操作自动运行,提高效率。 不知道从哪里听说的抖音 app 会导致 OLED 屏幕烧屏。于是就现学现卖,自...【详细内容】
2021-12-15  ITBang    Tags:抖音防烧屏   点击:(23)  评论:(0)  加入收藏
11 月 23 日,Rust Moderation Team(审核团队)在 GitHub 上发布了辞职公告,即刻生效。根据公告,审核团队集体辞职是为了抗议 Rust 核心团队(Core team)在执行社区行为准则和标准上...【详细内容】
2021-12-15  InfoQ    Tags:Rust   点击:(24)  评论:(0)  加入收藏
一个项目的大部分API,测试用例在参数和参数值等信息会有很多相似的地方。我们可以复制API,复制用例来快速生成,然后做细微调整既可以满足我们的测试需求1.复制API:在菜单发布单...【详细内容】
2021-12-14  AutoMeter    Tags:AutoMeter   点击:(20)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条