35

有什么区别-

newSingleThreadExecutor vs newFixedThreadPool(20)

从操作系统和编程的角度来看。

每当我使用我的程序运行我的程序时,newSingleThreadExecutor我的程序运行良好并且端到端延迟(第 95 个百分位)出现5ms

但是,一旦我开始使用-运行我的程序-

newFixedThreadPool(20)

我的程序性能下降,我开始看到端到端延迟为37ms.

所以现在我试图从架构的角度来理解线程数在这里意味着什么?以及如何确定我应该选择的最佳线程数是多少?

如果我使用更多的线程,那么会发生什么?

如果有人可以用外行语言向我解释这些简单的事情,那对我来说将非常有用。谢谢您的帮助。

我的机器配置规范-我正在从 Linux 机器运行我的程序-

processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 45
model name      : Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz
stepping        : 7
cpu MHz         : 2599.999
cache size      : 20480 KB
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology tsc_reliable nonstop_tsc aperfmperf pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes hypervisor lahf_lm arat pln pts
bogomips        : 5199.99
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

processor       : 1
vendor_id       : GenuineIntel
cpu family      : 6
model           : 45
model name      : Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz
stepping        : 7
cpu MHz         : 2599.999
cache size      : 20480 KB
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology tsc_reliable nonstop_tsc aperfmperf pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 popcnt aes hypervisor lahf_lm arat pln pts
bogomips        : 5199.99
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:
4

3 回答 3

54

行。理想情况下,假设您的线程没有锁定,因此它们不会相互阻塞(彼此独立)并且您可以假设工作负载(处理)是相同的,那么事实证明,池大小Runtime.getRuntime().availableProcessors()availableProcessors() + 1最好的结果。

但是,如果线程相互干扰或涉及 I/O,那么 Amadhal 定律可以很好地解释。从维基,

Amdahl 定律指出,如果 P 是程序可以并行化的比例(即,从并行化中受益),并且 (1 - P) 是不能并行化的比例(仍然是串行的),那么最大加速比可以是通过使用 N 个处理器实现的是

阿玛达尔法

在您的情况下,根据可用内核的数量,以及它们究竟做了什么工作(纯计算?I/O?持有锁?为某些资源阻塞?等等),您需要提出基于上述的解决方案参数。

例如:几个月前,我参与了从数字网站收集数据的工作。我的机器是 4 核的,我的池大小为4. 但是因为操作很纯粹I/O,而且我的网速​​也不错,我意识到我在池大小为7. 那是因为,线程不是为了计算能力而战,而是为了 I/O。所以我可以利用更多线程可以积极竞争核心的事实。

PS:我建议,通过 Brian Goetz 的书 - Java Concurrency in Practice 中的性能一章。它详细处理了这些问题。

于 2013-04-21T06:14:10.560 回答
7

所以现在我试图从架构的角度来理解线程数在这里意味着什么?

每个线程都有自己的堆栈内存、程序计数器(如指向下一步执行指令的指针)和其他本地资源。将它们交换出来会损害单个任务的延迟。好处是当一个线程空闲时(通常在等待 i/o 时)另一个线程可以完成工作。此外,如果有多个处理器可用,如果任务之间没有资源和/或锁定争用,它们可以并行运行。

以及如何确定我应该选择的最佳线程数是多少?

交换价格与避免空闲时间的机会之间的权衡取决于您的任务看起来像什么的小细节(多少 i/o,何时,在 i/o 之间有多少工作,使用多少内存完全的)。实验永远是关键。

如果我使用更多的线程,那么会发生什么?

首先,吞吐量通常会呈线性增长,然后是相对平坦的部分,然后是下降(可能非常陡峭)。每个系统都是不同的。

于 2013-04-21T06:17:06.030 回答
5

查看阿姆达尔定律很好,特别是如果您确切知道 P 和 N 有多大。由于这永远不会真正发生,您可以监控性能(无论如何您都应该这样做)并增加/减少线程池大小以优化对您而言重要的任何性能指标。

于 2013-04-21T21:48:09.193 回答