首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java ForkJoinPool挂在JDK17中

Java ForkJoinPool挂在JDK17中
EN

Stack Overflow用户
提问于 2022-08-24 14:01:27
回答 1查看 91关注 0票数 2

下面的代码可重用地使用JDK16,并在我的膝上型计算机(4/8核心)上使用基本命令行选项"-ea“可再现地挂起JDK17。JDK-票证存在(https://bugs.openjdk.org/browse/JDK-8281524),但使用方式是否“好”存在分歧。然后,在过去的6个月里,无线电保持沉默。有人能帮我找出我的使用错误(如果有的话),以及如何修复它吗?

代码语言:javascript
复制
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!
    }
}

更新1 (针对Stephen的评论):

考虑在自定义池中执行大量逻辑的示例。这不仅是“函数的重大损失”(因此在Open票证上出现了"Priority=P3“),因为这在JDK16中有效。它还显示了JDK17本身的不兼容性,因为我们显然不能再与集合框架一起使用自定义池了。我还是不确定该怎么解决这个问题。我唯一能想到的是,最初设计在公共池中运行的任何东西都必须被明确地提交到公共池中,这似乎是一个艰难的设计选择。我在看什么?

代码语言:javascript
复制
    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 ...
    }));
EN

回答 1

Stack Overflow用户

发布于 2022-08-24 15:26:51

我对Doug在票证上的解释是,造成问题的原因是您的用例导致了两个ForkJoinPool实例之间的工作共享,而这从来没有得到保证。

现在我明白了为什么分享会发生。javadoc for public static <T extends Comparable<? super T>> void parallelSort(T[] a)状态:

ForkJoin公共池用于执行任何并行任务。

因此,通过在调用parallelSort的自定义池中启动一个任务,您将设置跨池工作共享的条件。

答案似乎是“不要那样做”。不要从自定义parallelSort中的任务调用ForkJoinPoolArrays.parallelSort方法没有提供指定要使用的池的方法。相反,只需在公共池中启动任务即可。

我已通过更改来初步证实这一点:

代码语言:javascript
复制
    final ForkJoinPool fjPool = new ForkJoinPool(1);

在你的例子中

代码语言:javascript
复制
    final ForkJoinPool fjPool = ForkJoinPool.commonPool();

而且看起来很管用。这可能不是你想要的解决方案,但我认为这是你能得到的最好的解决方案,除非你能说服Doug等人:

  • 应该支持跨池工作共享,
  • 或者应该提供一种方法来告诉Arrays.parallelSort使用指定的ForkJoinPool

个人..。我不相信这些修正都是个好主意。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73474536

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档