scala - 使用并行集合时,批量执行哪些操作?奇怪的行为在这里

标签 scala parallel-processing scala-collections

在Scala REPL中输入以下小的顺序程序及其并行化版本:

/* Activate time measurement in "App" class. Prints [total <X> ms] on exit. */
util.Properties.setProp("scala.time", "true")
/* Define sequential program version. */
object X extends App { for (x <- (1 to 10)) {Thread.sleep(1000);println(x)}}
/* Define parallel program version. Note '.par' selector on Range here. */
object Y extends App { for (y <- (1 to 10).par) {Thread.sleep(1000);println(y)}}

使用X.main(Array.empty)执行X可以得到:
1
2
3
4
5
6
7
8
9
10
[total 10002ms]

而带有Y.main(Array.empty)的Y给出:
1
6
2
7
3
8
4
9
10
5
[total 5002ms]

到现在为止还挺好。但是该程序的以下两个变体呢?
object X extends App {(1 to 10).foreach{Thread.sleep(1000);println(_)}}
object Y extends App {(1 to 10).par.foreach{Thread.sleep(1000);println(_)}}

给我分别为 [total 1002ms] [total 1002ms] 的运行时。 怎么可能?

最佳答案

这与并行集合无关。该问题隐藏在函数文字中。如果让编译器显示AST(带有-Xprint:typer选项),则可以看到它:

for (x <- (1 to 10)) {Thread.sleep(1000);println(x)}

产生
scala.this.Predef.intWrapper(1).to(10).foreach[Unit](((x: Int) => {
  java.this.lang.Thread.sleep(1000L);
  scala.this.Predef.println(x)
}))

然而
(1 to 10).foreach{Thread.sleep(1000);println(_)}

产生
scala.this.Predef.intWrapper(1).to(10).foreach[Unit]({
  java.this.lang.Thread.sleep(1000L);
  ((x$1: Int) => scala.this.Predef.println(x$1))
})

有一点区别。如果您想要预期的结果,则必须将foreach-expression更改为
(1 to 10).foreach{x => Thread.sleep(1000);println(x)}

但是有什么区别呢?在您的代码中,您向foreach声明了一个块,执行完该块后,它将返回要执行的函数。然后,此返回的函数将传递给foreach,而不是包含该函数的块。

这个错误经常发生。它与下划线文字有关。也许this question可以帮助您。

关于scala - 使用并行集合时,批量执行哪些操作?奇怪的行为在这里,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7461942/

相关文章:

scala - 为什么 Scala stdlib 中没有 ARM?

c++ - 并发数组检查

c++ - pi 计算的 OpenMP 并行化速度慢或错误

scala - 将元组附加到元组的 MutableList 会出错

Scala 可变集合,插入时排序

scala - Scala 中并行集合的效率/可扩展性(图表)

scala - 对同一张 table 使用光滑的多重投影

VIM 和 Scala -- 缩进问题?

gcc - OpenMP - 线程如何决定何时推迟任务以及何时立即执行

scala - Scala + Gradle +仓库flatDir {}给了xsbti/CompileFailed错误