我发现JVM只使用一个线程池来并行处理流的困难方式。我们在大型流上有一个I / O阻塞函数,这会导致与不相关的并行流一起使用的不相关和快速函数的生动问题。
流上没有允许使用备用线程池的方法。
有没有一种简单的方法可以避免这个问题,或许以某种方式指定使用哪个线程池?
答案 0 :(得分:2)
您可以将阻止操作包装在ForkJoinPool.ManagedBlocker
中,沿着这一行:
static <T> Supplier<T> blocking(Supplier<T> supplier) {
return new Supplier<T>() {
volatile T result;
@Override
public T get() {
try {
ForkJoinPool.managedBlock(new ManagedBlocker() {
@Override
public boolean block() {
result = supplier.get();
return true;
}
@Override
public boolean isReleasable() {
return result != null;
}
});
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
return result;
}
};
}
然后使用它,例如:
Stream.generate(blocking(() -> ...))
.parallel()
...
.collect(...);
更多信息可以在这篇博文中找到: http://zeroturnaround.com/rebellabs/java-parallel-streams-are-bad-for-your-health/
jOOλ通过org.jooq.lambda.Blocking
为所有Java 8 FunctionalInterface
类型提供包装,如上所述,所以你可以写:
Stream.generate(Blocking.supplier(() -> ...))
.parallel()
...
.collect(...);
或者,例如当过滤器阻塞时:
Stream....
.parallel()
.filter(Blocking.predicate(t -> blockingTest(t)))
.collect(...);
(免责声明,我为jOOλ背后的公司工作)。
答案 1 :(得分:0)
这可能类似于Custom thread pool in Java 8 parallel stream
问题在this blog进一步讨论。
ForkJoinPool forkJoinPool = new ForkJoinPool(2);
forkJoinPool.submit(() ->
//parallel task here, for example
range(1, 1_000_000).parallel().filter(PrimesPrint::isPrime).collect(toList())
).get();