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)
理想情况下,我希望应用程序中使用的所有并行流都使用应用程序中的类加载器,而不是系统类加载器。
任何的想法?
如果可以选择使用第三方,您可以使用并行收集器库:
list.addAll(items
.stream()
.filter(item -> !SomeFilter.isOk(item.getId()))
.collect(parallel(logic::getSubItem, Collectors.toList(), forkJoinPool)
.join());
Run Code Online (Sandbox Code Playgroud)