我想知道我是否正确地写了这个,并获得任何进一步的细节或说明(特别是上下文切换的描述):
在我的计算机上(使用英特尔酷睿i7),我有四个核心,每个核心有两个 硬件线程(例如处理器,使用所谓的硬件技巧) 超线程)。虽然这是"最近"机 (在撰写本文时),您可能会看到一个不同的结果 - 以及一个 并行
Stream
程序中的默认线程数相等。事实证明"泛型"最佳线程数是 处理器可用(对于特定问题可能不是这样)。这来了 从线程之间的上下文切换的成本:存储当前状态 被挂起的线程和检索其他线程的当前状态 从进入暂停状态开始执行。如果你有八个处理器 在运行8个线程时,JVM永远不必切换上下文 任务。如果你的任务少于处理器数量,那么它就没有了 帮助分配更多线程。
注意:我将此与两个并行流和Executors.newWorkStealingPool()
产生(在我的机器上)8个线程的原因相关联。
注2:当您致电Runtime.getRuntime().availableProcessors()
时,它会在我的机器上返回8。所以我描述了Java认为是处理器的东西。"
答案 0 :(得分:3)
它并不那么简单;很大程度上取决于线程在做什么。如果您的线程都是计算密集型的,则最佳线程数可能与处理器核心数相同,以避免上下文切换的开销。但是,如果您的线程执行I / O,或者偶尔会阻塞资源,那么拥有比内核更多的线程可能是有利的,这样可以避免在线程被阻塞时浪费内核。
此外,英特尔超线程通常不会提高计算能力;该功能在硬件级别维护额外的线程上下文,但不会增加计算能力。因此,对于计算密集型线程,最好将线程数与物理核心数相匹配,并忽略超线程。当线程偶尔被阻塞时,超线程主要是有用的,因为当一个线程被阻塞时,可以避免上下文切换到处理器上的其他超线程的大部分成本。
注意:关于添加到问题中的附加说明,Java“看到”每个超线程作为处理器的事实基本上是英特尔过度炒作超线程所引入的错误;当活动线程的数量是物理处理器的数量而不是超线程的数量时,计算吞吐量被最大化,因此与机器自身的工作窃取池在目标线程数量等于物理处理器的数量的情况下最佳地工作。 Java的默认设置适用于大多数处理器,但在具有超线程的英特尔处理器上并不是最佳选择。如果您对其他详细信息感兴趣,我建议您查看另一个问题的答案,该问题描述了我在英特尔处理器上执行的最佳计算线程数的测试:
Multithreading - are the multi-core processors really doing parallel processing?