Scala并行打印导致控制台卡死

8

我是一个新手,正在尝试从一本书中练习Scala。所以,我有一个例子可以按顺序和并行方式打印向量。前者完美地工作,后者会挂起控制台。

代码

val v = Vector.range(0, 10)
v.foreach(println)

代码输出

0123456789

但是如果我使用相同的代码,但是不使用foearch,而是使用par,它会冻结控制台。

val v = Vector.range(0,10)
v.par.foreach(println)

我是一名有用的助手,可以为您翻译文本。
我正在使用的书中说,输出应该类似于:
5678901234    

但是它卡住了,程序永远无法完成。有人能解释一下为什么吗?

4
虽然不是很明显,但这是由于在静态初始化程序中启动线程所致。有一个相关的SO讨论,我会尝试找到它。具体链接为:https://issues.scala-lang.org/browse/SI-8119和https://dev59.com/jWUp5IYBdhLWcg3wmIUs。该票据提供了解决方法。最简单的方法是将其设置为局部变量,“{ x.par }”。 - som-snytt
2
我使用Scala 2.12.1进行了测试,控制台卡住了。使用Scala 2.11.8则正常工作。 - Andrzej Jozwik
谢谢大家的回答,我只是好奇原因。我目前没有在任何项目中使用它。 - Israel Zinc
我通过使用 scala -Yrepl-class-based 命令启动 REPL(参见此评论)使其正常工作,但是我尝试的其他方法都没有成功(包括在命令的各个部分中添加大括号)。 - turtlemonvh
进一步证据:这在默认的repl中有效:class X { Vector.range(0,10). par.foreach(print) } ; new X,但这个不行 object X { Vector.range(0,10). par.foreach(print) } ; X. - turtlemonvh
以下是另一个无法正常工作的示例:import scala.concurrent.forkjoin.ForkJoinPool; import scala.collection.parallel.ForkJoinTaskSupport; var v = Vector.range (0,10).par; v.tasksupport = new ForkJoinTaskSupport(new ForkJoinPool(4)); v.foreach(print)。我原以为显式地创建线程池可能有所帮助,但似乎它仍然是惰性求值的,并且我仍然遇到死锁问题。 - turtlemonvh
1个回答

1

最好发布整个卡住的程序。

我刚刚使用scala 2.12.8和jvm 1.8.0_161进行了测试:

object MainClassss {
  def main(args: Array[String]): Unit = {
    val v = Vector.range(0,10)
    (0 to 999999).foreach(_ => v.par.foreach(println))
  }
}

程序已经成功执行并输出,没有挂起。
如果您的程序出现了上述问题,您需要通过以下方式获取线程转储:
$ jstack <PID>

PID是进程ID。

或者你可以使用jvm工具jvisualvm进行查看。

如果程序有一些代码阻止其执行,你可以分析为什么程序被挂起,因为已捕获线程转储。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接