2015-05-13 16 views
4

这里是代码:在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] 

模式始终是 “主题[ForkJoinPool-1-工人 - ” $ { AnOddNumber} “5,主]”。有没有人有关于为什么工人的ID总是奇数而不是偶数的想法?

回答

2

您正在使用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 } 

希望它有帮助!

相关问题