为什么fork连接任务在公共fork连接池线程之外执行?

时间:2017-08-26 06:46:10

标签: java java.util.concurrent fork-join forkjoinpool

我可以通过提供代码段来解释我的问题:

public static void main(final String[] a) {
    Stream.of(1, 2, 3, 4).map(i -> ForkJoinPool.commonPool().submit(new RecursiveAction() {
        @Override
        protected void compute() {
            System.out.println(Thread.currentThread());
        }
    })).forEach(ForkJoinTask::join);
}

在具有4个核心的笔记本电脑上运行时,会打印出来:

Thread[main,5,main]
Thread[ForkJoinPool.commonPool-worker-1,5,main]
Thread[main,5,main]
Thread[ForkJoinPool.commonPool-worker-1,5,main]

为什么某些任务在主线程中运行,主线程是公共fork连接线程池之外的线程?

创建自定义fork join线程池时,不会发生这种情况:

public static void main(final String[] a) {
    final ForkJoinPool p = new ForkJoinPool(4);

    Stream.of(1, 2, 3, 4).map(index -> p.submit(new RecursiveAction() {
        @Override
        protected void compute() {
            System.out.println(Thread.currentThread());
        }
    })).forEach(ForkJoinTask::join);
}

Thread[ForkJoinPool-1-worker-1,5,main]
Thread[ForkJoinPool-1-worker-1,5,main]
Thread[ForkJoinPool-1-worker-1,5,main]
Thread[ForkJoinPool-1-worker-1,5,main]

那么,换句话说,公共池有什么特别之处?提供这些知识,在公共池中执行长时间运行的任务是明智的还是不明智的想法?

2 个答案:

答案 0 :(得分:5)

发生了一些相当聪明的事情。

当你从一个不在线程中的线程调用ForkJoinTask::join时,它会显示(来自ForkJoinPool.awaitJoin上的注释)当前线程可以“帮助”执行任务。

这就是主线程在fork-join池中执行任务的原因。

但是为什么在创建自定义池的情况下会有所不同?好吧,我的猜测是你的自定义池有足够的线程,不需要主线程。因为另一件事是默认情况下创建的“公共池”的一个线程少于可用处理器的数量。

有关详细信息,请查看源代码。请注意,此行为未在javadocs中指定,因此在将来的实现中可能会更改。

答案 1 :(得分:3)

阐述我的其他评论:

将提交线程用作工作线程一直是关于性能的。在工作窃取优先程序中,提交线程将新请求放入提交队列,并通知工作线程有工作。 (确切地知道哪些线程得到通知已经随着时间而改变。)

工作窃取线程只能通过窃取其他线程的deques或转到提交队列来获得工作。 (现在有多个提交队列,因为仅使用一个扩展问题。)线程如何找到工作是无关紧要的。相关的是它很慢。线程需要醒来然后去寻找工作。因为线程的队列是deques,所以无法为任何线程提供工作。这种设计的主要原因是作者从Cilk复制了设计。

Cilk是集群fork / join程序。它主要在计算机在网络中连接的集群环境中工作。拥有工作共享算法,其中计算机查询其他计算机的队列以查看工作的位置,或者将分叉任务放入哪里(进入具有最少数量的待处理任务以进行负载平衡的队列)是令人望而却步的。因此,在集群环境中,首先使用deques进行工作窃取。

在Java中,环境是共享内存。其他线程的队列中存在微不足道的开销。在任何情况下,对框架的第一个请求都要求从线程中唤醒,寻找工作并且速度很慢。

对于Java8并行流,系统需要公共池和加速进程的方法。 (并行线程的初始时间非常糟糕。)因此,作者想出了将提交线程用作工作者的想法。但是,这种技术引入了自己的问题,如下所述:http://coopsoft.com/ar/Calamity2Article.html#submission