我正在研究标准服务器应用程序。每个请求的处理分为几个阶段(第二阶段要求第一阶段完成,依此类推)。现在,其中一个阶段需要相当长的时间,但本身可以分解为几十个左右的任务,这些任务不依赖于彼此,因此可以并行化。我想向SlowStageService
添加一个线程池,我想知道如何最好地调整它。线程池最好在大多数时间内至少有一个空位,这意味着它必须以比服务器接收请求更快或更快的速度处理任务;这会产生一个合理的线程池大小下限。但是,我想对尺寸进行慷慨,因为计算中涉及的许多数字都可能会发生变化。
所以我的问题是:使我的游泳池太大(比如3或4)并且有很多空闲线程的缺点是什么?我知道它浪费了一些资源,但它实际上并没有保留任何CPU,因此不能用于其他请求,对吧?人们通常会有多少松懈?假设我计算了6个线程是我需要的最小值;在中等载荷的24芯盒子上说12可以安全吗?
当我写这篇文章时,听起来我可能需要的是ThreadPoolExecutor
范围相当窄(3或4x)?
答案 0 :(得分:6)
您应该参考Brian Goetz的Java Concurrency In Practice一书中的第8.2节。
如果您的阶段是计算密集型阶段并且I / O非常少,那么threadpool的最佳大小= CPU核心数+ 1(因此在您的情况下它将是25)。 但是,如果您的阶段中有I / O绑定任务,那么线程池实现最佳响应时间的最佳适用大小取决于各种因素:
NUM_THREADS = N * UC *(1+(W / C))
除上述指标外,影响池大小计算的其他因素还包括内存要求,连接池大小,文件句柄和套接字句柄。
鉴于调整线程池背后的上述理论;我的经验表明,达到最佳池大小的最佳方法是在各种工作负载下分析应用程序,并为轻,中,重工作负载大小提供池大小。
此外,永远不要硬编码最大线程池大小 - 它应该始终是一个可配置参数,以便可以根据遇到的工作负载在现场调整它。