Spring的ThreadPoolTask​​Executor的池大小问题

时间:2015-08-22 15:31:57

标签: java multithreading spring threadpool threadpoolexecutor

我正在对Spring应用程序进行一些负载测试,现在我对ThreadPoolTaskExecutor的配置感到有点困惑。

内部使用的ThreadPoolExecutor的文档将corePoolSize描述为“保留在池中的线​​程数,即使它们处于空闲状态,[...]”和{{1} } as“池中允许的最大线程数”。

这显然意味着maximumPoolSize限制了池中线程的数量。但相反,限制似乎由maximumPoolSize设定。实际上我只使用corePoolSize corePoolSize配置了100取消配置(这意味着使用了默认值:maximumPoolSize = Integer.MAX_VALUE)。

当我运行负载测试时,我可以看到(通过查看日志),执行的工作线程编号从2147483647worker-1。因此,在这种情况下,线程池大小受worker-100限制。即使我将corePoolSize设置为maximumPoolSize200,结果也完全相同。

为什么300的值对我的情况没有影响?

maximumPoolSize

我在文档中找到了解决方案:“如果有多个corePoolSize但运行的是不到maximumPoolSize线程,则只有在队列已满时才会创建新线程”。默认队列大小为@Bean public TaskExecutor taskExecutor() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(100); taskExecutor.setThreadNamePrefix("worker-"); return taskExecutor; } 。如果我限制队列,一切正常。

2 个答案:

答案 0 :(得分:9)

我已对ThreadPoolTaskExecutor进行了一些测试,您必须了解三件事:

  • corePoolSize
  • queueCapacity
  • maxPoolSize

启动进程时,池中没有线程。 每次任务到来时,只要未达到corePoolSize,就会创建一个新的执行程序线程来处理此新负载。 到达corePoolSize时,下一个任务将转移到队列并等待一个免费的执行程序线程。 如果加载过高且queueCapacity已满,则将创建新的执行程序线程,除非达到maxPoolSize。一旦队列为空,这些额外的线程将过期。 如果corePoolSize已用尽,queueCapacity已满,且maxPoolSize也已达到,那么新提交的任务将被拒绝并被调用将获得例外。

您尚未提及配置的queueCapacity,因此可能会将其设置为最高整数,因此永远不会触发maxPoolSize。尝试使用较小的corePoolSizequeueCapacity,您将看到所需的结果。

答案 1 :(得分:4)

如果池中有100个线程,并且您正在4个物理CPU核心上执行CPU绑定代码,则大多数核心线程在池中处于空闲状态,等待重新使用。这可能就是为什么你看到的不仅仅是worker-100。

您没有向我们展示您在工作人员中执行的代码,因此我认为它不受I / O限制。如果它是I / O绑定代码并且等待阻塞I / O操作完成将占用100个核心线程,ThreadPoolExecutor将需要创建其他工作程序。

尝试使用低于机器核心数的corePoolSize进行确认。另一种选择是将Thread.sleep(1000)放入您的工作人员代码中,并观察您的工人数量将如何增加。

编辑:

您建议在评论中使用SimpleAsyncTaskExecutor。请注意Spring Framework docs的这一部分:

  

SimpleAsyncTaskExecutor此实现不重用任何   线程,而不是为每次调用启动一个新线程。   但是,它确实支持并发限制,这将限制任何   超出限制的调用,直到插槽被释放。如果   你正在寻找真正的汇集,请参阅讨论   下面是SimpleThreadPoolTask​​Executor和ThreadPoolTask​​Executor。

因此,对于SimpleAsyncTaskExecutor,您根本没有池,并且在创建和删除Thread对象时浪费了大量资源(包括CPU周期),这可能是非常昂贵的操作。

因此,SimpleAsyncTaskExecutor执行程序类型对负载测试的弊大于利。如果您想拥有更多工人,请使用更多机器。如果你想要进行准确的负载测试,那么只使用一台机器是天真的。