one*_*eat 6 java contextclassloader forkjoinpool tomcat8 java-stream
在tomcat从8.5.6升级到8.5.28后,并行流停止为contexts提供contextClassLoader:
因为它Warmer::run无法在其中加载类.
warmers.parallelStream().forEach(Warmer::run);
Run Code Online (Sandbox Code Playgroud)
你有什么想法Tomcat为新线程提供contextClassLoaders的东西吗?
ParallelStream在最新的Tomcat中使用ForkJoinPool.
小智 8
这救了我的命!我必须这样做才能使其发挥作用:
private static class CustomForkJoinWorkerThread extends ForkJoinWorkerThread {
CustomForkJoinWorkerThread(ForkJoinPool pool) {
super(pool);
setContextClassLoader(Thread.currentThread().getContextClassLoader());
}
}
private ForkJoinPool createForkJoinPool() {
return new ForkJoinPool(
ForkJoinPool.getCommonPoolParallelism(),
CustomForkJoinWorkerThread::new,
null,
false
);
}
createForkJoinPool().submit(() -> stuff.parallelStream().doStuff())
Run Code Online (Sandbox Code Playgroud)
常见的ForkJoin池存在问题,可能导致内存泄漏以及能够从其他上下文/应用程序加载类和资源的应用程序(如果您的tomcat是多租户,则可能发生安全漏洞).请参阅此Tomcat Bugzilla报告.
在Tomcat 8.5.11中,他们通过介绍对上述问题进行了修复SafeForkJoinWorkerThreadFactory.java
为了使您的代码工作,你能做到以下几点,这将提供明确的ForkJoin及其工作线程工厂的Stream.parallel()执行.
ForkJoinPool forkJoinPool = new ForkJoinPool(NO_OF_WORKERS);
forkJoinPool.execute(() -> warmers.parallelStream().forEach(Warmer::run));
Run Code Online (Sandbox Code Playgroud)