我们需要在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;
我是否完全犯错了?我总是会遇到并发异常和堆栈溢出。我认为我没有正确连接递归任务,因为它始终会导致堆栈溢出。
答案 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
)。