为什么只有这一个特定的代码打破时,其他一切工作?
在注解掉for循环或join()时没有问题。只是两者都不起作用。
使用while循环可以工作,将循环放在另一个类中也可以工作,在REPL中工作,或者作为脚本而不将其 Package 为对象/类(使用@main),在Scala 2中工作。不适用于同一个类/对象中的函数中的循环
object Main extends App {
val t = new Thread() {
override def run() = {
println("Started")
for (j <- 1 to 2) {println("Work")}
}
}
t.start()
t.join()
}
编辑:
我说的不起作用是指意外行为:同样用Thread.sleep(3000)替换join(),新线程(包含for循环)只有在主线程结束休眠后才继续执行(从for循环开始)
可以在Scastie中测试
迭代任何集合似乎都会导致这个问题。For可以被替换为这个块,但它仍然不会打印
it = List(1, 2, 3)
it.foreach(x => println(x))
但这会打印出来,这不应该工作,因为这是foreach的定义
it = List(1, 2, 3)
while(it.hasNext) println(it.next())
1条答案
按热度按时间cwtwac6a1#
Scala 3 no longer treats
DelayedInit
the way Scala 2 did,结果App
的主体现在作为静态初始化器的一部分执行(就像任何其他object
一样)。除了加载类的线程之外的任何线程都将阻塞,直到静态初始化器完成为止(在这种情况下,静态初始化器甚至在App
的合成main
方法被调用之前就退出了)。在
Seq(1, 2).foreach { _ => println("Working") }
的情况下,{ _ => println("Working") }
的主体被吊出成为部件(可能是一个方法,尽管我没有检查字节码),因此对foreach
的调用被阻塞,直到Main
在JVM眼中是一个“真实的的对象”,直到静态初始化器完成。不幸的是,静态初始化器(感谢join
)正在等待foreach
完成。while
仍然由编译器进行特殊解释,并在字节码中变成循环。这可以通过不扩展
App
而仅将对join
的调用移动到main方法中(如this Scastie中)的最小更改来看出。(使Main
成为JVM眼中的真实的对象,从而允许分叉线程中的foreach
执行)。主方法被输入并且能够join
分叉线程。