在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/