Это работает, если вы преобразуете 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
, а диапазоны не являются, так сказать, "строгими". В хорошем английском языке, когда вы вызываете метод map
для Range
, он не вычисляет каждое значение прямо сейчас. Вместо этого он создает объект - RandomAccessSeq.Projection в Scala 2.7 - который имеет ссылку на функцию, переданную на карту, а другую - на исходный диапазон. Таким образом, когда вы используете элемент результирующего диапазона, функция, которую вы передали на карту, применяется к соответствующему элементу исходного диапазона. И это будет происходить каждый раз, когда вы получаете доступ к любому элементу результирующего диапазона.
Это означает, что каждый раз, когда вы ссылаетесь на элемент 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 res4
и res5
), полученное выражение снова оценивается. Это происходит и для отдельных элементов:
scala> test.t(1)
Called again! 2
res6: Int = 2
scala> test.t(1)
Called again! 2
res7: Int = 2
EDIT
Начиная с Scala 2.8, Range
будет строгим, поэтому код в вопросе будет работать так, как ожидалось.