如何确定线程池大小 推荐 原创 曹林华 2017-12-30 17:10:32 ©著作权 文章标签 线程池 文章分类 软件研发 ©著作权归作者所有:来自51CTO博客作者曹林华的原创作品,请联系作者获取转载授权,否则将追究法律责任 背景 在我们日常业务开发过程中,或多或少都会用到并发的功能。那么在用到并发功能的过程中,就肯定会碰到下面这个问题 并发线程池到底设置多大呢? 通常有点年纪的程序员或许都听说这样一个说法 (其中 N 代表 CPU 的个数) CPU 密集型应用,线程池大小设置为 N + 1 IO 密集型应用,线程池大小设置为 2N 这个说法到底是不是正确的呢? 其实这是极不正确的。那为什么呢? 首先我们从反面来看,假设这个说法是成立的,那我们在一台服务器上部署多少个服务都无所谓了。因为线程池的大小只能服务器的核数有关,所以这个说法是不正确的。那具体应该怎么设置大小呢? 假设这个应用是两者混合型的,其中任务即有 CPU 密集,也有 IO 密集型的,那么我们改怎么设置呢?是不是只能抛硬盘来决定呢? 那么我们到底该怎么设置线程池大小呢?有没有一些具体实践方法来指导大家落地呢?让我们来深入地了解一下。 Little's Law(利特尔法则) 一个系统请求数等于请求的到达率与平均每个单独请求花费的时间之乘积 假设服务器单核的,对应业务需要保证请求量(QPS):10 ,真正处理一个请求需要 1 秒,那么服务器每个时刻都有 10 个请求在处理,即需要 10 个线程 同样,我们可以使用利特尔法则(Little’s law)来判定线程池大小。我们只需计算请求到达率和请求处理的平均时间。然后,将上述值放到利特尔法则(Little’s law)就可以算出系统平均请求数。估算公式如下 线程池大小 = ((线程 IO time + 线程 CPU time )/线程 CPU time ) CPU数目* 具体实践 通过公式,我们了解到需要 3 个具体数值 一个请求所消耗的时间 (线程 IO time + 线程 CPU time) 该请求计算时间 (线程 CPU time) CPU 数目 请求消耗时间 Web 服务容器中,可以通过 Filter 来拦截获取该请求前后消耗的时间 public class MoniterFilter implements Filter { private static final Logger logger = LoggerFactory.getLogger(MoniterFilter.class); @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { long start = System.currentTimeMillis(); HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpRespOnse= (HttpServletResponse) response; String uri = httpRequest.getRequestURI(); String params = getQueryString(httpRequest); try { chain.doFilter(httpRequest, httpResponse); } finally { long cost = System.currentTimeMillis() - start; logger.info("access url [{}{}], cost time [{}] ms )", uri, params, cost); } private String getQueryString(HttpServletRequest req) { StringBuilder buffer = new StringBuilder("?"); Enumeration<String> emParams = req.getParameterNames(); try { while (emParams.hasMoreElements()) { String sParam = emParams.nextElement(); String sValues = req.getParameter(sParam); buffer.append(sParam).append("=").append(sValues).append("&"); } return buffer.substring(0, buffer.length() - 1); } catch (Exception e) { logger.error("get post arguments error", buffer.toString()); } return ""; } } CPU 计算时间 CPU 计算时间 = 请求总耗时 - CPU IO time 假设该请求有一个查询 DB 的操作,只要知道这个查询 DB 的耗时(CPU IO time),计算的时间不就出来了嘛,我们看一下怎么才能简洁,明了的记录 DB 查询的耗时。通过(JDK 动态代理/ CGLIB)的方式添加 AOP 切面,来获取线程 IO 耗时。代码如下,请参考 public class DaoInterceptor implements MethodInterceptor { private static final Logger logger = LoggerFactory.getLogger(DaoInterceptor.class); @Override public Object invoke(MethodInvocation invocation) throws Throwable { StopWatch watch = new StopWatch(); watch.start(); Object result = null; Throwable t = null; try { result = invocation.proceed(); } catch (Throwable e) { t = e == null ? null : e.getCause(); throw e; } finally { watch.stop(); logger.info("({}ms)", watch.getTotalTimeMillis()); } return result; } } CPU 数目 逻辑 CPU 个数 ,设置线程池大小的时候参考的 CPU 个数 cat /proc/cpuinfo| grep "processor"| wc -l 总结 合适的配置线程池大小其实很不容易,但是通过上述的公式和具体代码,我们就能快速、落地的算出这个线程池该设置的多大。不过最后的最后,我们还是需要通过压力测试来进行微调,只有经过压测测试的检验,我们才能最终保证的配置大小是准确的。 参考 Little's law 赞 收藏 评论 分享 举报 上一篇:系统思考 下一篇:全链路设计与实践 提问和评论都可以,用心的回复会被更多人看到 评论 发布评论 全部评论 () 最热 最新 相关文章 线程池模式 概念线程池模式(Thread Pool Pattern)是一种用于管理线程的设计模式。它通过预先创建一组线程,并维护一个任务队列,将需要执行的任务提交给线程池来执行,从而避免了频繁地创建和销毁线程的开销,提供了线程的重用和线程生命周期的管理。线程池模式的主要目标是提高线程的利用率、减少线程创建和销毁的开销,并且能够控制并发线程的数量,防止资源被过度消耗。以下是线程池模式的一些关键组件和特点: 线程池 任务队列 java Java 线程池 ThreadPoolExecutor 记录线程池的使用 线程池 java ide spring boot中一般如何使用线程池 在Spring Boot中,线程池作为并发编程的核心工具,对于提升应用程序性能、优化资源利用和保证系统稳定性具有重要作用。本文将详细阐述如何在Spring Boot中正确使用线程池,包括配置参数、实例化、任务提交、监控及常见问题处理等环节,并辅以代码示例,以期为开发者提供一份全面的实践指南。一、线程池基础线程池是一种基于池化技术管理线程的机制,其核心目标在于减少线程创建与销毁的开销,通过复用已创建 线程池 实例化 开发者 如何确定线程池的大小? 背景在我们日常业务开发过程中,或多或少都会用到并发的功能。那么在用到并发功能的过程中,就肯定会碰到下面这个问题并发线程池到底设置多大呢?通常有点年纪的程序员或许都听说这样一个说法 (其中 N 代表 CPU 的个数)CPU 密集型应用,线程池大小设置为 N + 1IO 密集型应用,线程池大小设置为 2N 这个说法到底是不是正确的呢?其实这是极不正确的。那为什么呢? 线程池 服务器 ide 压力测试 单核 线程池大小如何调? 在项目中经常使用到多线程来提升业务处理速度,但线程池的大小该定义为多大,这块该怎么确定?1.IO密集型单核心最佳线程数=1+(IO耗时/CPU耗时)多核心线程数星佳线程数=CPU核数*(1+(IO耗时/CPU耗时))注:如何获取CPU耗时和IO耗时,可以通过APM之类系统2.CPU密集型最佳线程数=CPU核数+1说明一下这个1哪来的,是为了防止突然有线程出现内存页失效或者其它原因导致阻塞;3.总结 线程池 线程池大小 如何设置线程池参数大小? 关注Java后端技术栈“回复“面试”获取最新资料我们在使用线程池的时候,会有两个疑问点:线程池的线程数量设置过多会导致线程竞争激烈如果线程数量设置 充分利用计算机... 线程池 Java System 如何设置Java线程池大小? 线程的概念 线程 线程是调度 CPU 资源的最小单位, 线程模型粉丝 KLT 模型与 ULT 模型,JVM 使用的是 KLT 模型, Java线程与 OS线程保持 1:1 的映射关系,也就是说有一个 Java JVM 线程池 java 阻塞队列 如何设定线程池的大小 from:http://blog.csdn.net/cothly/archive/2007/06/25/1665859.aspx只要您遵循几条简单的准则,线程池可以成为构建服务器应用程序的极其有效的方法:不要对那些同步等待其它任务结果的任务排队。这可能会导致上面所描述的那种形式的死锁,在那种死锁中,所有线程都被一些任务所占用,这些任务依次等待排队任务的结果,而这些任务又无法执行,因为所有的线程 职场 休闲 线程池 大小 如何合理线程池大小?(建议收藏) 面试必问! 线程池 如何合理估算 Java 线程池大小 这是根据大量的案例总结的Java线程池大小确定的公式,但在实操中所考虑的侧重点可能有不同,那么需要根据实际场景来微调互)。 java oracle 数据库 线程池 应用程序 java 确定线程池的大小 java线程池oom java基础之线程池为什么要使用线程池为什么不使用自动创建的线程池ThreadPoolExecutor 的核心参数 为什么要使用线程池第一点,反复创建线程系统开销比较大,每个线程创建和销毁都需要时间,如果任务比较简单,那么就有可能导致创建和销毁线程消耗的资源比线程执行任务本身消耗的资源还要大。 第二点,过多的线程会占用过多的内存等资源,还会带来过多的上下文切换,同时还会导致系统的不稳定。为什么不 java 确定线程池的大小 java 多线程 线程池 任务队列 RestHighLevelClient设置线程池大小 如何设置线程池参数 线程池参数(ThreadPoolExecutor)public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit uni 多线程 线程池 任务队列 上下文切换 如何合理设置线程池大小 要想合理的配置线程池的大小,首先得分析任务的特性,可以从以下几个角度分析:任务的性质:CPU密集型任务、IO密集型任务、混合型任务。 任务的优先级:高、中、低。 任务的执行时间:长、中、短。 任务的依赖性:是否依赖其他系统资源,如数据库连接等。性质不同的任务可以交给不同规模的线程池执行。对于不同性质的任务来说,CPU密集型任务应配置尽可能小的线程,如配置CPU个数+1的线程数,IO 线程池 java ide 等待时间 执行时间 如何获取SpringBoot线程池大小 springboot schedule 线程池 背景在真实的Java开发环境中,我们经常会需要用到定时任务来帮助我们完成一些特殊的任务,比如我最近写的晚上11点定时拉取第三方的数据入库,晚上12点清理脏数据等等。如果我们使用SpringBoot来开发,那么定时任务将会变得非常简单。SpringBoot默认已经帮我们封装好了相关定时任务的组件和配置,我们只需要在相应的地方加上@Schedule注解就可以实现定时任务。启动定时任务SpringBoo 如何获取SpringBoot线程池大小 java 多线程 springboot 定时任务 java如何查看dubbo 线程池大小 dubbo io线程池 Dubbo默认的底层网络通讯使用的是Netty,服务提供方NettyServer使用两级线程池,其中 EventLoopGroup(boss) 主要用来接受客户端的链接请求,并把接受的请求分发给 EventLoopGroup(worker) 来处理,boss和worker线程组我们称之为IO线程。如果服务提供方的逻辑能迅速完成,并且不会发起新的IO请求,那么直接在IO线程上处理会更快,因为这减少了 java如何查看dubbo 线程池大小 线程池 线程模型 提供方 java线程池如何动态管理核心线程池大小 java线程池动态调整 java线程池的实现原理简单使用架构分析线程池的实现原理一些重要的属性线程池的状态线程池状态间的转换workQueueworkerscorePoolSizemaximumPoolSizehandlerkeepAliveTimeallowCoreThreadTimeOutthreadFactorylargestPoolSizecompletedTaskCount构造函数提交任务执行缓存策略和排队策略 java 动态线程池 线程池 Java 实现原理 java项目怎么查看线程池大小 如何查看线程池线程数 查看线程死锁命令jstack [进程id]线程池的7个参数public ThreadPoolExecutor(int corePoolSize, //核心线程数 int maximumPoolSize, //最大线程数 long keepAliveTime, //最大线程空闲时间 java项目怎么查看线程池大小 java 面试 经验分享 线程池 java 如何设置netty线程池大小 netty默认线程池数量 如果你在简历上写了Netty,那么面试官百分之九十的可能会问你Netty默认其多少线程?在什么时候启动的问题。面试官一方面是想考验你对Netty有没有最基本的知识点掌握,一方面是想试探你有没有深入了解过Netty的源码和启动流程。 你在编写Netty服务端的时候经常会编写下面的代码:EventLoopGroup boss = new NioEventLoopGroup();Even java 如何设置netty线程池大小 java spring 开发语言 netty Java线程池ArrayBlockingQueue默认大小 java 线程池大小 今天来跟大家分享一下Java线程池的大小设置。 0 前言 在我们日常业务开发过程中,或多或少都会用到并发的功能。那么在用到并发功能的过程中,就肯定会碰到下面这个问题 并发线程池到底设置多大呢? 通常有点年纪的程序员或许都听说这样一个说法 (其中 N 代表 CPU 的个数)1.CPU 密集型应用,线程池大小设置为 N + 1 线程池 服务器 ide java调整dubbo线程池大小 dubbo默认线程池大小 线程池Dubbo有两种线程池,第一种是I/O线程池,第二种是业务线程池。I/O线程池主要是收包发包,接收新的连接,业务线程则是执行我们的业务代码(调用接口的实现类)。I/O线程数默认是CPU的个数+1,业务线程数默认是200。与其他半同步半异步的模型相似,Dubbo的业务线程池也配备了队列,不过队列容量的默认值是0,也即是不使用队列来缓存处理不过来的请求;关于这点,官方文档是这么解释的:“线程池队 java调整dubbo线程池大小 线程池 业务逻辑 缓存