从ForkJoinPool的RecursiveTask收集List <Long>结果

时间:2019-06-24 10:11:09

标签: java recursion primes fork-join

我们需要在forkjoinpool中将素因子计算分为多个递归任务。

我们有一个素数列表和一个工作负载大小,例如5。 因此,如果要计算50的素数,则将所有素数都设为25,然后计算素数。 WorkloadSize是单个递归任务将处理的素数的数量。

我做了什么:

Long[] workLoad = new Long[primes.size()];
workLoad = primes.toArray(workLoad);

pool = new ForkJoinPool();
ForkJoinWorker worker = new ForkJoinWorker(workLoad, q, partitionSize, 0);
pool.execute(worker);

resultList =  worker.invoke();

workLoad =所有质数的数组。

q =我们要为其计算素数的数字。

ForkJoinWorker扩展了RecursiveTask>

在递归任务中,我查看workLoadSize是否大于Ive得到的素数数组,如果是,则创建一个新的

ForkJoinWorker f = new ForkJoinWorker(..);
f.fork();
List<Long> results = calcFactors(...);
results.addAll(f.join);
return results;

我是否完全犯错了?我总是会遇到并发异常和堆栈溢出。我认为我没有正确连接递归任务,因为它始终会导致堆栈溢出。

1 个答案:

答案 0 :(得分:0)

完整的堆栈跟踪和更完整的代码示例应有助于阐明正在发生的事情。但是,在您显示的代码中还有几件事。

调用主要任务

在您的示例中,您进行

pool.execute(worker);
resultList =  worker.invoke();

这不是它应该工作的方式。

调用“ execute”可以分派任务,这很好,但是不会等待它完成。因此,您刚刚启动了计算,没有完成或结果的句柄。

您自己通常不会进行自行调用invoke的事情,应该让pool本身调用此方法。因为它将在调用线程中开始执行任务,而没有任何池的支持。因此,如果您以不合逻辑的顺序join,甚至可能陷入僵局。

调用RecursiveTask<T>的“预期”方式是调用pool.invoke(task),这将返回T(计算结果)或pool.submit(task)将会返回Future

任务之间的共享状态

任务中的这段代码可能有问题:

List<Long> results = calcFactors(...);
results.addAll(f.join);

如果calcFactors创建自己的List返回,它将起作用。但是,如果此列表在任务之间共享,则意味着多个任务(和线程)可以在同一实例上执行addAll,这仅在列表能够支持它的情况下才有效(我认为唯一的并发{{ JDK中的1}}是List)。