创建大型固定线程池的后果

ale*_*lex 2 java concurrency multithreading threadpool

我正在研究标准服务器应用程序.每个请求的处理分为几个阶段(第二阶段要求第一阶段完成,依此类推).现在,其中一个阶段需要相当长的时间,但本身可以分解为几十个左右的任务,这些任务不依赖于彼此,因此可以并行化.我想添加一个线程池SlowStageService,并想知道如何最好的大小.线程池最好在大多数时间内至少有一个空位,这意味着它必须以比服务器接收请求更快或更快的速度处理任务; 这会产生一个合理的线程池大小下限.但是,我想对尺寸进行慷慨,因为计算中涉及的许多数字可能会发生变化.

所以我的问题是:让我的游泳池太大(比如3或4)并且有很多闲置线程的缺点是什么?我知道它浪费了一些资源,但它实际上并没有保留任何CPU,因此不能用于其他请求,对吧?人们通常会有多少松懈?假设我计算了6个线程是我需要的最小值; 在中等载荷的24芯盒子上说12可以安全吗?

正如我写的那样,听起来我可能需要的是ThreadPoolExecutor一个相当窄(3或4x)的范围?

Pra*_*nde 6

您应该参考Brian Goetz的Java Concurrency In Practice一书中的8.2节.

如果您的阶段是计算密集型阶段并且I/O非常少,那么threadpool的最佳大小= CPU核心数+ 1(因此在您的情况下它将是25).但是,如果您的阶段中存在I/O绑定任务,那么线程池实现最佳响应时间的最佳适用大小取决于各种因素:

  1. CPU数量 - N.
  2. 目标CPU利用率 - UC
  3. I/O操作(W)的等待时间(阻塞状态)与计算时间(C)的比率.

NUM_THREADS = N*UC*(1+(W/C))

除上述指标外,影响池大小计算的其他因素还包括内存要求,连接池大小,文件句柄和套接字句柄.

鉴于以上理论背后调整线程池的大小; 我的经验表明,达到最佳池大小的最佳方法是在各种工作负载下分析应用程序,并为轻,中,重工作负载大小提供池大小.

此外,永远不要硬编码最大线程池大小 - 它应该始终是一个可配置参数,以便可以根据遇到的工作负载在现场调整它.