5

我写了以下代码段:

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 个核心。

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

提前致谢。

4

2 回答 2

5

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

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

它将compute()所有参数,compute()如果未满足工作人员阈值,则由方法负责委托和分叉,然后在完成时加入计算。(尽管以两种以上的方式拆分它是不寻常的——fork join 通常通过每次递归将工作负载拆分为两个来工作,如果需要的话。)

于 2013-06-03T12:16:29.607 回答
0

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

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

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

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

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

于 2013-06-05T12:12:51.397 回答