gpt4 book ai didi

scala - Thread.join 在 scala 中的行为不符合我的预期

转载 作者:行者123 更新时间:2023-12-03 00:11:33 29 4
gpt4 key购买 nike

在下面的代码中,我创建了 20 个线程,让它们每个打印一条消息,休眠,然后打印另一条消息。我在主线程中启动线程,然后也加入所有线程。我希望只有在所有线程完成后才会打印“全部完成”消息。然而,“全部完成”在所有线程完成之前就被打印出来了。有人可以帮助我理解这种行为吗?

谢谢。肯特

这是代码:

  def ttest() = {
val threads =
for (i <- 1 to 5)
yield new Thread() {
override def run() {
println("going to sleep")
Thread.sleep(1000)
println("awake now")
}
}

threads.foreach(t => t.start())
threads.foreach(t => t.join())
println("all done")
}

这是输出:

going to sleep
all done
going to sleep
going to sleep
going to sleep
going to sleep
awake now
awake now
awake now
awake now
awake now

最佳答案

如果将 Range 转换为 List,它就会起作用:

  def ttest() = {
val threads =
for (i <- 1 to 5 toList)
yield new Thread() {
override def run() {
println("going to sleep")
Thread.sleep(1000)
println("awake now")
}
}

threads.foreach(t => t.start())
threads.foreach(t => t.join())
println("all done")
}

问题在于“1 to 5”是一个Range,可以说,范围并不“严格”。用良好的英语来说,当您在 Range 上调用方法 map 时,它不会立即计算每个值。相反,它会生成一个对象(Scala 2.7 上的 RandomAccessSeq.Projection),该对象具有对传递给 map 的函数的引用和另一个对原始范围的引用。因此,当您使用结果范围的元素时,传递给 map 的函数将应用于原始范围的相应元素。每次您访问结果范围的任何元素时都会发生这种情况。

这意味着每次引用 t 的元素时,都会重新调用 new Thread() { ... }。由于您执行了两次,并且该范围有 5 个元素,因此您将创建 10 个线程。您从前 5 个开始,然后在后 5 个加入。

如果这令人困惑,请查看下面的示例:

scala> object test {
| val t = for (i <- 1 to 5) yield { println("Called again! "+i); i }
| }
defined module test

scala> test.t
Called again! 1
Called again! 2
Called again! 3
Called again! 4
Called again! 5
res4: scala.collection.generic.VectorView[Int,Vector[_]] = RangeM(1, 2, 3, 4, 5)

scala> test.t
Called again! 1
Called again! 2
Called again! 3
Called again! 4
Called again! 5
res5: scala.collection.generic.VectorView[Int,Vector[_]] = RangeM(1, 2, 3, 4, 5)

每次我打印 t(通过让 Scala REPL 打印 res4res5),生成的表达式都会再次求值。对于单个元素也会发生这种情况:

scala> test.t(1)
Called again! 2
res6: Int = 2

scala> test.t(1)
Called again! 2
res7: Int = 2

编辑

从 Scala 2.8 开始,Range 将很严格,因此问题中的代码将按最初预期工作。

关于scala - Thread.join 在 scala 中的行为不符合我的预期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1313979/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com