从 8 个并行流升级的 Java 11 抛出 ClassNotFoundException

Pav*_*its 7 java parallel-processing spring java-stream java-11

我将 Spring Boot 应用程序从 Java 8 和 tomcat 8 升级到了 java 11 和 tomcat 9。除了我在列表上使用并行流的部分外,一切似乎都运行良好。

list.addAll(items
                .parallelStream()
                .filter(item -> !SomeFilter.isOk(item.getId()))
                .map(logic::getSubItem)
                .collect(Collectors.toList()));
Run Code Online (Sandbox Code Playgroud)

前一部分代码过去在 Java 8 和 Tomcat 8 上工作得很好,但在Java 9 改变了如何使用 Fork/Join 公共池线程加载类之后,将系统类加载器作为它们的线程上下文类加载器返回。

我知道在后台并行流使用 ForkJoinPool 并且我创建了一个自定义 bean 类,但仍然没有被应用程序使用。很可能是因为它们可能是在这个 bean 之前创建的。

@Bean
public ForkJoinPool myForkJoinPool() {
    return new ForkJoinPool(threadPoolSize, makeFactory("APP"), null, false);
}

private ForkJoinPool.ForkJoinWorkerThreadFactory makeFactory(String prefix) {
    return pool -> {
        final ForkJoinWorkerThread worker = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool);
        worker.setName(prefix + worker.getPoolIndex());
        worker.setContextClassLoader(Application.class.getClassLoader());
        return worker;
    };
}
Run Code Online (Sandbox Code Playgroud)

最后,我还尝试将它包装在我的 ForkJoinPool 实例周围,但它是异步完成的,我不想这样做。我也不想使用提交和获取,因为这意味着我必须用 try/catch 包装我在应用程序中拥有的所有并行流,并且代码将很难阅读。

forkJoinPool.execute(() -> 
  list.addAll(items
                .parallelStream()
                .filter(item -> !SomeFilter.isOk(item.getId()))
                .map(logic::getSubItem)
                .collect(Collectors.toList())));
Run Code Online (Sandbox Code Playgroud)

理想情况下,我希望应用程序中使用的所有并行流都使用应用程序中的类加载器,而不是系统类加载器。

任何的想法?

man*_*uti 1

如果可以选择使用第三方,您可以使用并行收集器库:

list.addAll(items
            .stream()
            .filter(item -> !SomeFilter.isOk(item.getId()))
            .collect(parallel(logic::getSubItem, Collectors.toList(), forkJoinPool)
            .join());
Run Code Online (Sandbox Code Playgroud)