怎样设置Java线程池的大小

  

小编给大家分享一下怎样设置Java线程池的大小,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

在我们日常业务开发过程中,或多或少都会用到并发的功能。那么在用到并发功能的过程中,就肯定会碰到下面这个问题

并发线程池到底设置多大呢?

通常有点年纪的程序员或许都听说这样一个说法 (其中 N 代表 CPU 的个数)

  1. CPU 密集型应用,线程池大小设置为 N + 1

  2. IO 密集型应用,线程池大小设置为 2N

这个说法到底是不是正确的呢?

其实这是极不正确的。那为什么呢?

首先我们从反面来看,假设这个说法是成立的,那我们在一台服务器上部署多少个服务都无所谓了。因为线程池的大小只能服务器的核数有关,所以这个说法是不正确的。那具体应该怎么设置大小呢?

假设这个应用是两者混合型的,其中任务即有 CPU 密集,也有 IO 密集型的,那么我们改怎么设置呢?是不是只能抛硬盘来决定呢?

那么我们到底该怎么设置线程池大小呢?有没有一些具体实践方法来指导大家落地呢?让我们来深入地了解一下。

Little's Law(利特尔法则)

怎样设置Java线程池的大小

一个系统请求数等于请求的到达率与平均每个单独请求花费的时间之乘积

假设服务器单核的,对应业务需要保证请求量(QPS):10 ,真正处理一个请求需要 1 秒,那么服务器每个时刻都有 10 个请求在处理,即需要 10 个线程

怎样设置Java线程池的大小

同样,我们可以使用利特尔法则(Little's law)来判定线程池大小。我们只需计算请求到达率和请求处理的平均时间。然后,将上述值放到利特尔法则(Little's law)就可以算出系统平均请求数。估算公式如下

*线程池大?((线程 IO time + 线程 CPU time )/线程 CPU time ) CPU数目**

具体实践

通过公式,我们了解到需要 3 个具体数值

  1. 一个请求所消耗的时间 (线程 IO time + 线程 CPU time)

  2. 该请求计算时间 (线程 CPU time)

  3. CPU 数目

请求消耗时间

Web 服务容器中,可以通过 Filter 来拦截获取该请求前后消耗的时间

public class MoniterFilter implements Filter { 
  private 才能static  final  Logger  Logger =, LoggerFactory.getLogger (MoniterFilter.class);,
  @Override 才能;
  doFilter (public 才能;void  ServletRequest 请求,ServletResponse 反应,FilterChain 链),throws  IOException,,
  ,,,,,ServletException  {,
  ,,,long  start =, System.currentTimeMillis (),,
  ,,,HttpServletRequest  httpRequest =, (HttpServletRequest),请求,,
  ,,,HttpServletResponse  httpResponse =, (HttpServletResponse),反应;,
  ,,,String  uri =, httpRequest.getRequestURI (),,
  ,,,String  params =, getQueryString (httpRequest);,
  ,,,try  {,
  ,,,,,chain.doFilter (httpRequest, httpResponse);,
  ,,,},finally  {,
  ,,,,,long  cost =, System.currentTimeMillis(),背后,开始,,
  ,,,,,logger.info (“access  url  [{} {}], cost  time ({}),小姐),,,uri,,参数,,成本),,
  ,,,},
  private 才能;String  getQueryString (HttpServletRequest 要求),{,
  ,,,StringBuilder  buffer =, new  StringBuilder (“?”),,
  ,,,Enumeration, 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时间

怎样设置Java线程池的大小