我写了以下代码:
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()
并在所有其他参数上分叉?
提前致谢。
答案 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()在所有任务运行后返回。