9

我拿了一个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似乎以类似的方式工作,搜索更多的值,即使文档说“元素可能不一定是迭代顺序中的第一个这样的元素”和“选择是不确定的”。

4

2 回答 2

2

为什么它不在找到第一个结果后立即向其他线程发送消息以中止任务?

因为那是不可能的。JAVA 不允许你这样做。或者,更确切地说,它确实如此,但它已被弃用。

请参阅(已弃用)的描述Thread.stop()

这种方法本质上是不安全的。使用 Thread.stop 停止线程会导致它解锁所有已锁定的监视器(这是未经检查的 ThreadDeath 异常沿堆栈传播的自然结果)。如果以前受这些监视器保护的任何对象处于不一致状态,则损坏的对象将对其他线程可见,从而可能导致任意行为。停止的许多用法应该由简单地修改一些变量以指示目标线程应该停止运行的代码替换。目标线程应该定期检查这个变量,如果变量指示它要停止运行,则以有序的方式从它的run方法返回。如果目标线程等待很长时间(例如,在条件变量上),应该使用中断方法来中断等待。有关详细信息,请参阅为什么不推荐使用 Thread.stop、Thread.suspend 和 Thread.resume?.

换句话说,因为带锁的多线程代码本质上是被破坏的,所以他们弃用了一种完美的方法,该方法可以愉快地与不共享可变状态的线程一起使用,因此不需要锁定数据结构。

于 2011-12-12T13:21:03.923 回答
1

我理解这种愿望,因为我认为自己有这样的行为会很好——从使用快速退出代码的意图来看,期待它看起来是合理的,但是当然,它应该如何实现呢?

在快捷方式表达式中,如果找到结果,则不会启动下一个调用 - 这很容易。

但是你如何跑到一个被解雇的任务后面,然后再次抓住它来阻止它呢?您需要知道其中哪些已经完成,并且可能会进入竞争状态,因为在测试时,无论它是否仍在运行,它可能会返回“真”,但之后会立即完成。

内部调用的函数exists可以自己启动新线程 - 一般如何从外部停止它们?通过提供可选的stop execution方法作为第二个参数?

于 2011-12-12T07:06:30.857 回答