在Java中创建线程池的最佳方法是什么

时间:2019-06-11 03:17:03

标签: java executorservice

我试图在我的一个应用程序中使用执行程序服务,在该应用程序中我创建了8个池,因为我的机器具有4个内核,并且根据最近的搜索,我发现一个内核上只能有2个活动线程。 当我通过java检查内核数时,也发现该值为4

int cores = Runtime.getRuntime().availableProcessors();
ExecutorService executor = Executors.newFixedThreadPool(cores*2);

请建议我做的是否正确,因为当我的cpu只能处理8个线程时,我看不出有太多的价值创建500个池。

2 个答案:

答案 0 :(得分:2)

超线程

您应该阅读hyper-threading技术。该术语专门用于Intel用于其专有的simultaneous multithreading (SMT)实现的品牌名称,但更广泛地用于SMT。

过于简单的解释:

在常规CPU中,线程之间的切换非常昂贵。寄存器是CPU内核实际处理的几条数据的存放地。切换线程时,必须将这些寄存器中的值换出。同样,也可以清除缓存(保存数据的位置,比寄存器慢,但比RAM快)。这一切都需要时间。

CPU中的超线程设计会添加一组重复的寄存器。每个内核都有一组寄存器,这意味着它可以在线程之间切换而无需交换寄存器中的值。线程之间的切换要快得多,以至于CPU依赖于操作系统,将每个内核报告为一对(虚拟)内核。例如,一个4核芯片将显示为8核。

  

我发现一个核心上只能有2个活动线程

请注意,切换线程仍然有一些开销,而开销却低得多。超线程CPU内核一次仍仅执行一个线程。超线程意味着线程之间的切换更加轻松快捷。

对于在线程通常处于等待模式的机器上,等待某些外部功能(例如通过网络调用)完成的机器,超线程非常有意义。对于内核可能会执行CPU限制的工作(例如数字运算,模拟,科学数据分析)的应用程序,那么超线程可能没有那么有用。因此,在执行此类工作的计算机上,系统管理员可能会决定禁用超线程,因此4个内核实际上只是4个内核。同样,由于与超线程技术有关的recent security vulnerabilities,一些系统管理员可能会决定禁用超线程。

线程池

  

当我的CPU仅能处理8个线程时,创建500个池。

线程池的大小取决于您应用程序的行为。如果具有与CPU绑定的应用程序,那么您当然希望将此类CPU密集型线程的数量限制为少于实际或虚拟内核的数量。如果您的应用程序不受CPU限制,如果它们经常执行file I/O,网络I / O或其他活动,而它们在等待其他资源时却无所作为,那么您的线程数可能会比内核数多。如果您的线程经常闲置无事,那么您可以拥有更多线程。

  

在Java中创建线程池的最佳方法是什么

此处没有没有具体规则可以帮助您。您必须首先进行有根据的猜测,然后在生产中监视您的应用和主机。因此,您可能需要一种方法来设置运行时在应用程序中使用的线程数,而不是对数字进行硬编码。例如,使用首选项设置或使用JMX。学习使用诸如Java Flight RecorderMission Control之类的分析工具;两者现在都与基于OpenJDK的Java发行版捆绑在一起。如果您要部署到支持DTrace的系统(macOS,BSD等),这也可能会有所帮助。

在一个具有在不同功能部分中进行的各种工作负载的应用程序中,维护多个线程池可能很有意义。使用线程数量很少的池来进行CPU密集型工作,而线程数量更多的池来进行CPU密集型工作。现代Java中的Executors框架可以简化这一过程。

考虑所有您可能要部署到计算机上的应用程序。并考虑该计算机上运行的所有其他应用程序。并考虑到操作系统的CPU需求。这样做之后,您可能会发现某些线程池最多只能设置为一个或两个线程。

棘手的东西

线程安全性是一项非常棘手的复杂工作。在线程(变量,文件等)之间共享资源时,您必须教育自己有关保护这些资源免遭滥用的问题。

必读:Java Concurrency in Practice等人的Brian Goetz

答案 1 :(得分:0)

转到System properties并检查其中有多少cores (physical cores)logical processors (virtual cores)

例如:

如果您的系统具有 n个内核 n个逻辑处理器 。这意味着您的处理器不支持hyperthreading

如果您的系统具有 n个内核 n x 2个逻辑处理器 。这意味着您的处理器支持hyperthreading。您可以并行执行n * 2个线程。

注意:假设您具有超线程支持。现在,您有8个核心和16个虚拟核心。

然后,处理器将提供高达16个线程的良好吞吐量。如果将线程池增加到超过16个线程,吞吐量将变得均匀并且不会变化太多。