Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java parallelStream()与调用方工作窃取的自定义池?_Java_Java 8_Java Stream_Fork Join_Forkjoinpool - Fatal编程技术网

Java parallelStream()与调用方工作窃取的自定义池?

Java parallelStream()与调用方工作窃取的自定义池?,java,java-8,java-stream,fork-join,forkjoinpool,Java,Java 8,Java Stream,Fork Join,Forkjoinpool,通常,当使用Java8的parallelStream()时,结果是通过默认的公共fork-join池(即ForkJoinPool.commonPool())执行 然而,如果一个人的工作远离CPU限制,例如可能大部分时间都在等待IO,那么这显然是不可取的。在这种情况下,需要使用一个单独的池,大小根据其他标准确定(例如任务实际使用CPU的时间) 没有明显的方法让parallelStream()使用不同的池,但有一种方法非常详细 不幸的是,这种方法需要从fork-join池线程调用并行流上的终端操作。

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

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

没有明显的方法让parallelStream()使用不同的池,但有一种方法非常详细

不幸的是,这种方法需要从fork-join池线程调用并行流上的终端操作。这样做的缺点是,如果目标fork-join池完全忙于现有的工作,那么整个执行将等待它,而完全不做任何事情。因此,池可能成为比单线程执行更糟糕的瓶颈。相反,当以“正常”方式使用parallelStream()时,ForkJoinPool.common.externalHelpComplete()或ForkJoinPool.common.tryExternalUnpush()用于让池外的调用线程帮助处理


有人知道一种方法可以让parallelStream()使用非默认的fork-join池,并让fork-join池外部的调用线程帮助处理这项工作(但不包括fork-join池的其余工作)?

您可以在池上使用
waitquisition
。但是,您无法选择要帮助的任务,它只会从池中获取下一个挂起的任务,因此,如果有更多挂起的任务,您可能会在开始自己的任务之前执行这些任务

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());
将永远挂起,因为它试图执行第二个阻塞任务

尽管如此,它仍会让启动线程帮助处理池的挂起任务,这将提高其自身任务被执行的机会,只要没有无限的任务(上面的示例是极端的,仅用于演示)



但是请注意,Fork/Join框架和
API之间的整个关系无论如何都是一个实现细节。

我不理解您的想法,其缺点是如果目标Fork-Join池完全忙于现有工作。难道你不会为这个并行流调用创建一个新的池吗?它甚至更糟。当您对不在公共池中的任务调用
get
时,它仍然会调用
ForkJoinPool.common.tryExternalUnpush()
,但是,当然,在公共池的队列中找不到该任务。要回答这个问题,不,我不会仅为此调用创建新的线程池。我宁愿在许多类似的调用中共享另一个线程池,其中一些调用可能会重叠,一些调用的任务可能比其他调用长得多/大得多,等等。我已经得出结论,我可以做到这一点,但正如您所指出的,这很可能意味着我最终会帮助其他线程完成任务,而不是帮助我自己工作。这是一种非启动。另外,我知道fork-join是一个实现细节,但是需要更好地控制parallelStream(),例如像parallelStream(forkJoinPool)这样简单的东西。好吧,使用类似
parallelStream(forkJoinPool)
的方法,它将不再是一个实现细节……不,但是什么是parallelStream()如果没有参数,does仍然是一个实现细节。这只会给你一个选择,在你需要的情况下采取一些控制。
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());