invokeAll它是如何工作的? (ForkJoin)

时间:2013-06-03 11:52:23

标签: java recursion fork-join

我写了以下代码:

static private int counter;

    public void compute()
    {
        if (array.length<=500)
        {

            for(int i = 0;i<array.length;i++){
                counter++;
                System.out.println("Ciao this is a recursive action number"+ counter+Thread.currentThread().getName()); 
            }
        }
        else{
        int split = array.length/2;
        RecursiveActionTry right = new RecursiveActionTry(split);
        RecursiveActionTry left = new RecursiveActionTry(split);
        invokeAll(right, left);

我看到invokeAll()自动分叉我传递给的两个RecursiveActionTry对象中的一个。我的笔记本电脑只有2个内核..如果我有4个内核并启动4个任务怎么办... invokeAll(right, left, backward, forward);我会使用所有4个内核吗?不知道因为我只有2个核心。

我还想知道invokeAll(右,左)是否在幕后为第一个参数(右)调用compute(),为第二个参数调用fork + join(左)。 (如在RecursiveTask扩展中应该是)。否则它不会使用并行性,是吗? 顺便说一句,如果有超过2个参数..它是否在第一个上调用compute()并在所有其他参数上分叉?

提前致谢。

2 个答案:

答案 0 :(得分:4)

invokeAll()调用许多在不同线程上独立执行的任务。这并不需要为每个线程使用不同的核心,但是如果它们可用,它可以允许为每个线程使用不同的核心。细节由底层机器处理,但基本上(简单地说)如果可用的核心少于线程,则它会对线程进行切片,以便允许一个核心在一个核心上执行一段时间,然后是另一个核心,然后是另一个核心(在循环中。)

  

顺便说一句,如果有超过2个参数..它是否在第一个上调用compute()而在所有其他上调用?

它将compute()所有参数,如果不满足工作者阈值,则委托和分配compute()方法的责任,然后在copmlete时加入计算。 (拆分它超过两种方式是不寻常的 - fork连接通常适用于每次递归,如果需要,将工作负载分成两部分。)

答案 1 :(得分:0)

任务和工作线程是不同的东西:

WorkerThreads由ForkJoinPool管理,如果你使用默认构造函数,它会根据Runtime.getRuntime().availableProcessors()启动WorkerThreads。

任务由您创建/管理。要使多个内核忙,您必须启动多个任务。您可以将每个分为两个部分或分为N个部分。当一个部分直接执行时,另一个部分被放入等待队列中。如果池中的任何其他WorkerThreads处于空闲状态并且没有工作要做,则应该从队列中“窃取”分叉的挂起任务并并行执行它们。

要获得8个核/ WorkerThread忙,不必一次调用8个任务。至少将两个任务分叉(递归地),直到所有WorkerThread都饱和(假设你的整体问题分成多个子任务)就足够了。 因此,如果您拥有更多或更少的内核,则无需调整代码,而您的任务根本不应该担心WorkerThread管理。

最后,invokeAll()或join()在所有任务运行后返回。