Java 8并行流+任意匹配-一旦找到匹配项,线程会被中断吗?

23
如果我在Java 8中有一个并行流,并使用anyMatch终止,并且我的集合有一个与谓词匹配的元素,那么当一个线程处理此元素时,我想知道会发生什么。
我知道anyMatch是短路的,因此一旦处理匹配元素,我不希望进一步处理其他元素。我的困惑在于其他正在处理元素的线程会发生什么。我可以想到三种可能的情况: a)它们被中断吗? b)它们继续处理它们正在处理的元素,然后,一旦所有线程都不执行任何操作,我就得到了结果? c)我得到了结果,但是正在处理其他元素的线程继续处理这些元素(但完成后不再接受其他元素)?
我的谓词运行时间很长,因此一旦知道一个元素匹配就能快速终止非常有用。我有点担心,因为我在文档中找不到这些信息,它可能是实现相关的事情,这也是需要知道的。
谢谢
1个回答

45

经过查看Java源代码,我认为我找到了答案。

其他线程会定期检查是否有另一个线程找到了答案,如果是,则它们停止工作并取消所有尚未运行的节点。

java.util.Stream.FindOps$FindTask有这个方法:

private void foundResult(O answer) {
        if (isLeftmostNode())
            shortCircuit(answer);
        else
            cancelLaterNodes();
    }

它的父类AbstractShortcircuitTask实现了shortCircuit方法,实现如下:

 /**
 * Declares that a globally valid result has been found.  If another task has
 * not already found the answer, the result is installed in
 * {@code sharedResult}.  The {@code compute()} method will check
 * {@code sharedResult} before proceeding with computation, so this causes
 * the computation to terminate early.
 *
 * @param result the result found
 */
protected void shortCircuit(R result) {
    if (result != null)
        sharedResult.compareAndSet(null, result);
}

而实际执行工作的compute()方法有这一重要行:

 AtomicReference<R> sr = sharedResult;
    R result;
    while ((result = sr.get()) == null) {
        ...//does the actual fork stuff here
    }

shortCircuit() 方法更新了 sharedResult,这样下一次计算时就会看到它并检查 while 循环条件。

编辑 总结:

  1. 线程不会被中断
  2. 相反,它们会定期检查是否有人找到答案,如果已经找到答案,则停止进一步处理。
  3. 一旦找到答案,就不会启动新的线程。

5
关于实现代码的信息非常详细,但我建议添加一份概述,最后回答提问者的问题,即“会发生什么”,即 b - Holger
有人能澄清一下吗 - 这是否也适用于noneMatch和allMatch操作?因此,如果allMatch的线程找到一个不匹配的元素,其他线程会定期检查,然后由于这个结果而停止吗? - Tranquility

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接