我应该在Java程序中使用多少线程?

我应该在Java程序中使用多少线程?,java,multithreading,Java,Multithreading,我最近继承了一个小型Java程序,它从一个大型数据库中获取信息,进行一些处理,并生成有关信息的详细图像。最初的作者使用单个线程编写代码,然后对其进行了修改,以允许它使用多个线程 在代码中,他定义了一个常数 // number of threads public static final int THREADS = Runtime.getRuntime().availableProcessors(); 然后设置用于创建图像的线程数 我理解他的推理,即线程的数量不能大于可用处理器的数量,因此将

我最近继承了一个小型Java程序,它从一个大型数据库中获取信息,进行一些处理,并生成有关信息的详细图像。最初的作者使用单个线程编写代码,然后对其进行了修改,以允许它使用多个线程

在代码中,他定义了一个常数

//  number of threads
public static final int THREADS =  Runtime.getRuntime().availableProcessors();
然后设置用于创建图像的线程数

我理解他的推理,即线程的数量不能大于可用处理器的数量,因此将其设置为充分发挥处理器潜力的数量。这是正确的吗?还是有更好的方法来充分利用处理器的潜力


编辑:为了进一步说明,正在线程化的特定算法将缩放到正在创建的图片的分辨率(每像素1个线程)。但这显然不是最好的解决方案。这个算法所做的工作需要花费所有的时间,完全是数学运算,没有锁或其他因素会导致任何给定的线程休眠。我只想最大限度地提高程序的CPU利用率,以缩短完成时间。

应用程序所需的数量;不多也不少

显然,如果您正在编写一个包含一些可并行算法的应用程序,那么您可能可以开始基准测试,以在线程数量上找到一个良好的平衡,但请记住,数百个线程不会加快任何操作


如果您的算法不能并行化,那么没有多少额外的线程会有帮助。

一方面,您认为线程==CPU/内核是非常有意义的。如果没有运行线程,为什么还要有线程

细节归结为“线程在做什么”。空闲等待网络数据包或磁盘块的线程浪费了CPU时间

如果线程占用大量CPU,那么1:1的关联就有一定意义。如果有一个“readthedb”线程为其他线程提供数据,还有一个“dumpthedata”线程从CPU线程中提取数据并创建输出,那么这两个线程很可能很容易共享一个CPU,而CPU繁忙的线程却在不停地搅动


与所有事情一样,真正的答案是衡量它。由于号码是可配置的(显然),请配置它!以1:1线程到CPU、2:1、1.5:1等方式运行它,并对结果计时。快一个赢。

是的,这是一个非常合理的方法。每个处理器/核心一个线程将最大限度地提高处理能力并最小化上下文切换。除非通过基准测试/评测发现问题,否则我可能会保持原样

需要注意的一点是,JVM不能保证
AvailableProcessor()
是常量,因此从技术上讲,在生成线程之前,您应该立即检查它。不过,我怀疑,在典型的计算机上,这个值在运行时可能会发生变化


另外,正如其他人所指出的,如果您的进程不受CPU限制,那么这种方法不太可能是最优的。既然您说这些线程用于生成图像,那么我假设您是CPU受限的。

处理器数量是一个良好的开端;但是如果这些线程执行大量i/o,那么使用更多的线程可能会更好。。。或者更少

首先考虑哪些资源可用,以及您希望优化哪些资源(完成时间最少,对其他任务的影响最小,等等)。然后做数学题


有时,如果您为每个i/o资源分配一两个线程,而其他线程则为CPU而斗争,这可能会更好。在这些设计中,分析通常更容易。

使用线程的好处是,允许程序在作业的不同部分上工作,而另一部分在等待某些事情发生(通常是I/O),从而减少程序的挂钟执行时间。如果您的程序完全受CPU限制,那么添加线程只会降低它的速度。如果它是完全或部分I/O绑定的,添加线程可能会有所帮助,但在添加线程的开销和将要完成的额外工作之间需要找到一个平衡点。如果程序完全或接近完全受CPU限制,使线程数等于处理器数将产生最高性能

正如许多问题中有“应该”一词一样,答案是“视情况而定”。如果您认为可以获得更好的性能,可以调整线程的数量,并对应用程序的性能进行基准测试。还要考虑可能影响决策的任何其他因素(如果您的应用程序消耗了计算机100%的可用马力,则其他应用程序的性能将降低)

这假设多线程代码编写正确等等。如果最初的开发人员只有一个CPU,他将永远不会有机会遇到编写糟糕的线程代码的问题。因此,在调整线程数时,您可能应该测试行为和性能


顺便说一下,您可能需要考虑允许在运行时配置线程的数量,而不是编译时间,以使整个过程更容易。

在看到您的编辑后,很可能每一个CPU的线程都是一样好的。您的应用程序似乎相当可并行化。如果你有额外的硬件,你可以使用GridGain来启用你的应用,并让它在多台机器上运行。除了购买更快/更多的内核之外,这可能是唯一一件可以加快速度的事情。

线程很好,但正如其他人所指出的,您必须高度意识到自己的瓶颈。您的算法听起来很容易受到多个CPU之间缓存争用的影响-这尤其令人讨厌,因为它可能会影响所有线程的性能(通常您会考虑在等待缓慢或高延迟IO操作时使用多个线程继续处理)