java – 在Scala的“未来”的ForkJoinPool中,为什么工人的ID总是奇数?

这是代码:

import scala.concurrent._
import ExecutionContext.Implicits.global
import scala.concurrent.duration._


val is = 1 to 100 toList
def db = s"${Thread.currentThread}"
def f(i: Int) = Future { println(db) ; 2 * i }

val theFuture = Future.traverse(is)(f _)

Await.result(theFuture, 10.seconds)

我跑了很多次,结果看起来像这样:

Thread[ForkJoinPool-1-worker-3,5,main]
Thread[ForkJoinPool-1-worker-3,5,main]
Thread[ForkJoinPool-1-worker-3,5,main]
Thread[ForkJoinPool-1-worker-3,5,main]
Thread[ForkJoinPool-1-worker-3,5,main]
Thread[ForkJoinPool-1-worker-1,5,main]
Thread[ForkJoinPool-1-worker-5,5,main]
Thread[ForkJoinPool-1-worker-7,5,main]
Thread[ForkJoinPool-1-worker-7,5,main]
Thread[ForkJoinPool-1-worker-7,5,main]
Thread[ForkJoinPool-1-worker-7,5,main]
Thread[ForkJoinPool-1-worker-7,5,main]
Thread[ForkJoinPool-1-worker-7,5,main]
Thread[ForkJoinPool-1-worker-7,5,main]
Thread[ForkJoinPool-1-worker-7,5,main]
Thread[ForkJoinPool-1-worker-3,5,main]

模式总是“Thread [ForkJoinPool-1-worker – ”${AnOddNumber}“,5,main]”.有没有人有关于为什么工人的ID总是奇数而不是偶数的想法?

最佳答案 您正在使用ExecutionContext.Implicits.global执行上下文.在引擎盖下,它使用ForkJoinPool来处理工作线程.这个ForkJoinPool由Scala库开发人员分叉,以便根据他们的需要对其进行修改.你可以找到它
here.

请参阅名为registerWorker的函数.构造工作者的名称构造添加前缀(这是名为workerNamePrefix的变量,默认值为“ForkJoinPool – ${POOL_ID} -worker-”),其池索引始终作为奇数计算(see line 1712).因此,无论如何,这个数字总是奇数.这是由于实现,避免扫描工作队列数组,而是将其视为二次幂哈希表(需要奇怪的索引进行双重哈希.你可以查看一些关于哈希表的好文档来查找更多关于它).

因此,您只需获得1,3,5和7作为工作人员编号,因为您可能拥有4核计算机.如果您希望它们在输出中显示更多分布,只需在工作中添加一些延迟,以便让其他工作人员也忙.像这样:

def f(i: Int) = Future { println(db); Thread.sleep(100); 2 * i }

希望它有所帮助!

点赞