我取一个List[Int]
,并想要搜索一个值x
,其中x * 10 > 500
平行。因此,如果列表包含51或更大的值,exists
应该返回true
。
def f(x: Int) = {
println("calculating for " + x)
Thread.sleep(100 - x)
println("finished " + x)
x * 10
}
val res = List.range(1, 100).par.exists(f(_) > 500)
给出结果:
calculating for 1
calculating for 25
calculating for 50
calculating for 75
calculating for 13
finished 75 // <-- first valid result found: 75 * 10 > 500
finished 50
calculating for 51 // but it kicks off more expensive calculations
finished 25
calculating for 26
finished 13
calculating for 14
finished 1
calculating for 2
finished 51
finished 26
calculating for 27 // and more
finished 14
calculating for 15
finished 2
calculating for 3
finished 27
calculating for 28
finished 15
calculating for 16
finished 3
calculating for 4 // and more...
finished 28
calculating for 29
finished 16
calculating for 17
finished 29
calculating for 30
finished 4
calculating for 5
finished 17
calculating for 18
finished 30
finished 5
calculating for 6
finished 18
finished 6
res: Boolean = true
我使用的是双核机器和Scala 2.9.1。
这是怎么回事?这是预期的工作吗?为什么它不把消息发送给其他线程,以便在找到第一个结果后立即中止任务呢?如果f
是一个昂贵的计算,那么这可能会非常昂贵。
find
似乎以类似的方式工作,搜索更多的值,尽管文档说"元素不一定是迭代顺序中的第一个这样的元素"one_answers"选择是不确定的"。
为什么它不直接把消息发送给其他线程去中止呢第一个结果出来后立即执行任务?
因为那不可能。Java不允许这样做。或者,更确切地说,它有,但不推荐使用。
参见(已弃用)Thread.stop()
:
这个方法本质上是不安全的。使用thread .stop停止线程使其解锁已锁定的所有监视器(作为未经检查的ThreadDeath异常传播的自然后果向上堆叠)。如果任何对象先前受这些保护监视器处于不一致状态时,损坏的对象变为对其他线程可见,可能导致任意行为。stop的许多用法应该被简单修改一些的代码所取代变量指示目标线程应停止运行。的目标线程应该定期检查这个变量,并从如果变量指示它以有序的方式运行它的方法就是停止奔跑。如果目标线程等待了很长时间(在条件变量(例如),应该使用中断方法打断等待。有关更多信息,请参见为什么是Thread.stop,线程。suspend和Thread。弃用?恢复。
换句话说,因为带锁的多线程代码本质上是被破坏的,所以他们弃用了一个非常好的方法,这个方法可以很好地用于不共享可变状态的线程,因此,不需要锁定数据结构。
我理解的愿望,因为我认为自己会很好,有这样的行为-从意图使用快速退出代码,它看起来合理的期望它,但当然,它应该如何实现?
在快捷表达式中,如果找到结果,则不开始下一个调用——这很容易。
但是你如何运行在一个给定的任务后面,并再次捕获它来停止它呢?您需要知道它们中哪些已经完成,并且可能进入竞争状态,因为在测试时,它是否仍在运行,它可能返回"true",但之后立即完成。
在exists
内部调用的函数可以自己启动新的线程-它们应该如何以一般的方式从外部停止?通过提供一个可选的stop execution
-方法作为第二个参数?