以下代码可重复地与 JDK16 一起使用,并在我的笔记本电脑(4/8 核)上使用 JDK17 可重复地挂起,并使用基本命令行选项:“-ea”。存在 JDK 票证(https://bugs.openjdk.org/browse/JDK-8281524 https://bugs.openjdk.org/browse/JDK-8281524),但对于这种用法是否“好”存在分歧。然后,无线电在过去 6 个月里保持沉默。有人可以帮助查明我的使用错误(如果有)以及如何修复它吗?
import java.util.Arrays;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.Stream;
import org.junit.Test;
public class FjpTest {
@Test
public void testFjp() {
final ForkJoinPool fjPool = new ForkJoinPool(1);
final String[] objs = Stream.generate(() -> "").limit(10_000).toArray(String[]::new);
// the following line should sort the array,
// but instead causes a single-threaded spin-wait
fjPool.invoke(ForkJoinTask.adapt(() -> Arrays.parallelSort(objs))); // this hangs!
}
}
Update 1(回应 Stephen C 的评论):
考虑这个示例,其中大量逻辑在自定义池中执行。这似乎不仅仅是“功能的重大损失”(因此 Open-JDK 票证上的“Priority=P3”),因为这在 JDK16 中有效。它还显示出 JDK17 本身的不兼容性,因为我们显然不能再将自定义池与集合框架一起使用。我仍然不确定如何解决这个问题。我唯一能想到的是,任何最初设计为在公共池中运行的东西都必须明确提交到公共池,这似乎是一个艰难的设计选择。我在忽略什么?
new ForkJoinPool(1).invoke(ForkJoinTask.adapt(() -> {
// ... some really smart and deep business logic in a ginormous application using
// a custom ForkJoinPool, when an innocent developer or a library for that matter
// (not even realizing that it runs inside a custom ForkJoinPool) decides
// to use the collections framework ...
Arrays.parallelSort(Stream.generate(() -> "").limit(10_000).toArray(String[]::new));
// ... dead code from here ...
}));
我对 Doug Lea 在票证上所说内容的解释是,问题的原因是您的用例导致两个人之间共享工作ForkJoinPool
实例,而且这永远不能保证有效。
现在我明白为什么会发生共享了。这javadoc https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html#parallelSort(T%5B%5D) for public static <T extends Comparable<? super T>> void parallelSort(T[] a)
state:
The ForkJoin
公共池用于执行任何并行任务。
因此,通过在调用的自定义池中启动任务parallelSort
您正在设置跨池工作共享的条件。
答案似乎是“不要这样做”。不要打电话parallelSort
来自自定义任务ForkJoinPool
. The Arrays.parallelSort
方法不提供指定要使用的池的方法。相反,只需在公共池中启动您的任务即可。
我通过更改暂时确认了这一点:
final ForkJoinPool fjPool = new ForkJoinPool(1);
在你的例子中
final ForkJoinPool fjPool = ForkJoinPool.commonPool();
这似乎有效。这可能不是您想要的解决方案,但我认为这是您能得到的最好的解决方案,除非您能说服 Doug Leaet al that:
- 应支持跨池工作共享,
- 或者应该提供一种方法来告诉
Arrays.parallelSort
使用指定的ForkJoinPool
.
就我个人而言......我不相信这些修复中的任何一个都是一个好主意。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)