带有调用者工作窃取的自定义池的Java parallelStream()?

时间:2015-10-01 15:39:14

标签: java java-8 java-stream fork-join forkjoinpool

通常当使用Java 8的parallelStream()时,结果是通过默认的公共fork-join池(即ForkJoinPool.commonPool())执行。

然而,如果一个人的工作远离CPU限制,那么这显然是不可取的。可能在很多时候都在等待IO。在这种情况下,人们会想要使用一个单独的池,根据其他标准确定大小(例如,任务可能实际使用CPU的时间有多少)。

没有显而易见的让parallelStream()使用不同的池的方法,但有一种方法详细here

不幸的是,这种方法需要从fork-join池线程调用并行流上的终端操作。这样做的缺点是,如果目标分支连接池完全忙于现有工作,整个执行将等待它,而什么都不做。因此,池可能成为比单线程执行更糟糕的瓶颈。相比之下,当一个人在" normal"中使用parallelStream()时fashion,ForkJoinPool.common.externalHelpComplete()或ForkJoinPool.common.tryExternalUnpush()用于让来自池外的调用线程帮助处理。

有没有人知道两者的方法让parallelStream()使用非默认的fork-join池有一个来自fork-join外部的调用线程池帮助处理这项工作(但不是其余的fork-join池'

1 个答案:

答案 0 :(得分:2)

您可以在游泳池上使用-s来提供帮助。但是,您无法选择要提供帮助的任务,它只会从池中获取下一个待处理项,因此,如果有更多待处理任务,您可能最终会在执行这些任务之前执行这些任务。

awaitQuiescence

将打印ForkJoinPool forkJoinPool = new ForkJoinPool(1); // make all threads busy: forkJoinPool.submit(() -> LockSupport.parkNanos(Long.MAX_VALUE)); // submit our task (may contain your stream operation) ForkJoinTask<Thread> task = forkJoinPool.submit(() -> Thread.currentThread()); // help out while(!task.isDone()) // use zero timeout to execute one task only forkJoinPool.awaitQuiescence(0, TimeUnit.NANOSECONDS); System.out.println(Thread.currentThread()==task.get());

,而

true

会在尝试执行第二个阻止任务时永远挂起。

然而,只要没有无限的任务,它就会让启动线程帮助处理池的挂起任务,这将增加自己的任务执行的可能性(上面的示例是极端的,只是为了演示而选择)。 / p>

但请注意,Fork / Join框架和ForkJoinPool forkJoinPool = new ForkJoinPool(1); // make all threads busy: forkJoinPool.submit(() -> LockSupport.parkNanos(Long.MAX_VALUE)); // overload: forkJoinPool.submit(() -> LockSupport.parkNanos(Long.MAX_VALUE)); // submit our task (may contain your stream operation) ForkJoinTask<Thread> task = forkJoinPool.submit(() -> Thread.currentThread()); // help out while(!task.isDone()) forkJoinPool.awaitQuiescence(0, TimeUnit.NANOSECONDS); System.out.println(Thread.currentThread()==task.get()); API之间的整个关系无论如何都是一个实现细节。