Java 性能进程与线程

我正在Java中实现一个工作线程池。

这本质上是一整个对象负载,这些对象将拾取数据块,处理数据,然后存储结果。由于 IO 延迟,工作线程将明显多于处理器内核。

服务器专用于此任务,我想从硬件中获得最大性能(但是我不想C++实现它)。

最简单的实现是使用单个 Java 进程来创建和监视多个工作线程。另一种方法是为每个工作线程运行一个 Java 进程。

假设为了论证,四核Linux服务器,你预计这些解决方案中的哪一个会更高性能,为什么?

您可以假设工作人员永远不需要相互通信。


答案 1

一个进程,多个线程 - 出于几个原因。

在作业之间切换上下文时,在某些处理器上,在线程之间切换比在进程之间切换更便宜。在这种 I/O 绑定的情况下,这一点尤其重要,因为工作线程比内核多。在阻止 I/O 之间所做的工作越多,这一点就越不重要。不过,良好的缓冲将为线程进程付费。

当在同一 JVM 中的线程之间切换时,至少某些 Linux 实现(尤其是 x86)不需要刷新缓存。请参阅Tsuna的博客。线程之间的缓存污染将最小化,因为它们可以共享程序缓存,执行相同的任务,并共享相同的代码副本。我们谈论的是每个开关节省100纳秒到几微秒的费用。如果这对您来说是小土豆,请继续阅读...

根据设计的不同,一个进程的 I/O 数据路径可能会更短。

线程的启动和预热时间通常要短得多。操作系统不必启动进程,Java不必启动另一个JVM,类加载只完成一次,JIT编译只完成一次,HotSpot优化完成一次,而且更快。


答案 2

通常,当在同一进程中讨论多处理(每个进程一个线程/w)与多线程时,虽然第一种情况下的理论开销大于后者(因此多处理理论上比多线程慢),但实际上在大多数现代操作系统上,这不是一个大问题。但是,在Java上下文中讨论它时,启动新进程比启动新线程的成本要高得多。启动新进程意味着启动 JVM 的新实例,这非常昂贵,尤其是在内存方面。我建议您在同一个 JVM 中启动多个线程。

此外,如果你说线程间通信不是问题,你可以使用Java的执行器服务来获得一个大小为2x(可用CPU数量)的固定线程池。可用 CPU 的数量可以在运行时通过 Java 的 Runtime 类自动检测。通过这种方式,您可以获得快速简单的多线程,而无需任何样板代码。


推荐