Parallel processing 流处理线程池耗尽
我发现JVM只使用一个线程池来并行处理流,这是一个艰难的过程。我们在一个大的流上有一个I/O阻塞函数,这导致了与不相关的并行流一起使用的不相关或其他快速函数的活跃性问题 流上没有允许使用备用线程池的方法Parallel processing 流处理线程池耗尽,parallel-processing,java-8,threadpool,java-stream,Parallel Processing,Java 8,Threadpool,Java Stream,我发现JVM只使用一个线程池来并行处理流,这是一个艰难的过程。我们在一个大的流上有一个I/O阻塞函数,这导致了与不相关的并行流一起使用的不相关或其他快速函数的活跃性问题 流上没有允许使用备用线程池的方法 有没有一种简单的方法可以避免这个问题,也许可以指定使用哪个线程池?这可能与 这一问题将在本文中进一步讨论 我编写了一个名为的小型库,它可以向自定义FJP提交任务。这样你就可以写作了 ForkJoinPool forkJoinPool = new ForkJoinPool(2); int[] pr
有没有一种简单的方法可以避免这个问题,也许可以指定使用哪个线程池?这可能与 这一问题将在本文中进一步讨论
我编写了一个名为的小型库,它可以向自定义FJP提交任务。这样你就可以写作了
ForkJoinPool forkJoinPool = new ForkJoinPool(2);
int[] primes = IntStreamEx.range(1, 1_000_000)
.parallel(forkJoinPool)
.filter(PrimesPrint::isPrime).toArray();
它只需记住您的池并启动池内的终端操作即可加入结果。只是前面提到的解决方案的一个语法糖。您可以将阻塞操作包装为一个,大致如下:
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;
}
};
}
更多信息可在此博客帖子中找到:
通过为所有Java 8functional接口
类型提供包装器,如上面所述,因此您可以编写:
Stream.generate(Blocking.supplier(() -> ...))
.parallel()
...
.collect(...);
或者,例如,当过滤器堵塞时:
Stream....
.parallel()
.filter(Blocking.predicate(t -> blockingTest(t)))
.collect(...);
(免责声明,我为jOOλ背后的公司工作)。可能的重复有一个技巧——在上面的链接问题中建议——但你应该记住,流主要是一种并行计算机制,而不是IO,因此你是在边缘操作。我们正在研究如何将这些用例更多地带入主流。@ BrangoEtz,当我听到你的耳朵时,请考虑API的扩展,也许是
Seq
的目的是“固定”流
,以便顺序(和有序)使用CompletableFuture
还将任务发送到ForkJoinPool
,因此您可能会耗尽相同的线程。我同意这种用法可能不是人们应该做的。但话说回来,什么是阻塞(在这种情况下)?是I/O吗?它是一个循环直到1\u 000\u 000\u 000
?这是一个愚蠢的指数算法吗?OP明确地说这是I/O。使用CF可以创建任意多的任务,但使用并行流您无法控制它。在4核机器上,通常会创建多达16个任务,如果其中15个任务在I/O操作中被阻塞,那么即使使用您的技巧,也只有一个任务会继续工作。流API将不再分割输入,也不会为您创建更多任务。
Stream.generate(Blocking.supplier(() -> ...))
.parallel()
...
.collect(...);
Stream....
.parallel()
.filter(Blocking.predicate(t -> blockingTest(t)))
.collect(...);