Java ForkJoin Future似乎过早地完成了

时间:2011-03-09 18:04:51

标签: java multithreading concurrency threadpool

我是jsr166y库的新手,我使用forkjoin库编写了一个例程,该库分割查询并同时对数据库副本运行它。我在下面放了一个片段。 SelectTask扩展了RecursiveTask。

ForkJoinExecutor fjPool;
    Future queryResultsFut = null;
      for (int i = 1; i <= lastBatchNum; i++) {

...

  SelectTask selectMatchesRecursiveTask = new SelectMatchesTask(loadBalancer.getDao(), thisRuleBatch, queryResults);
  queryResultsFut = fjPool.submit(selectMatchesRecursiveTask);
}

queryResultsFut.get();

对get方法的调用旨在阻止父线程,直到返回所有查询结果,以便可以对聚合结果开始处理。

我已经发现,在CI环境中运行一段时间之后,这并不总是会发生。当存在慢速数据库时,即使任务仍在运行,线程也将继续。在我看来,这与我读过的文档相矛盾。

也许我会以错误的方式解决这个问题?我应该扩展ForkJoinTask而不是RecursiveTask吗?

3 个答案:

答案 0 :(得分:3)

你可能根本不应该使用ForkJoin。 FJ框架专为CPU密集型非阻塞任务并行性而设计,但您专门用于阻塞任务(外部数据库查询)。我建议你使用正常的执行器框架来完成你想要做的事情。

与您的问题相匹配的FJ的唯一方面是任务分解。通过简单的n-way划分或更复杂的递归策略,这不会太难以手动滚动。

答案 1 :(得分:1)

RecursiveTask从ForkJoinTask继承了它的get功能,因此扩展ForkJoinTask不会产生不同的效果。请记住,每次提交时,都会返回不同的ForkJoinTask。你调用fjPool.submit多少次了?如果你做的更多,那么一旦你将获得你提交的最后一个任务,那么queryResultsFut将在最后一个任务完成时完成(即从get返回)。

由于您现在正在处理ForkJoin池,因此您应该在提交而不是Future之后返回ForkJoinTask。 JF框架的主要目的是分而治之的处理。当你能够将一个问题分解成更小的类似问题,并行执行它们然后组合结果并返回时,它是最有用的。

答案 2 :(得分:0)

尝试使用另一个fork-join方法: http://www.coopsoft.com/ar/ForkJoinArticle.html