【问题标题】:Java Fork Join Pool Timing IssueJava Fork 加入池时间问题
【发布时间】:2015-04-29 14:59:15
【问题描述】:

我正在尝试实现一个 Fork Join Pool,它将获取一个节点的子节点并同时探索它们。但是我认为我的 fork join pool 执行了线程然后关闭太快,导致线程停止执行?

到目前为止,我有这个代码:

主要方法:

    while (!(pqOpen.IsEmpty())) 
    {       
        tempVertex = pqOpen.GetNextItem();        
        if (tempVertex.city == endLocation.city)  
        {
            resetVertex();           
            return tempVertex;         
        }
        else 
        {                            
            ForkJoinPool forkJoinPool = new ForkJoinPool(tempVertex.neighbors.GetNoOfItems());
            for (int i = 0; i < tempVertex.neighbors.GetNoOfItems(); i++) //for each neighbor of tempVertex
            {
                forkJoinPool.execute(new NeighbourThread(tempVertex, allVertices, routetype, pqOpen, i, endLocation));

            }
            forkJoinPool.shutdown();
        }
    }
    return null;
}   

这是我运行的课程:

public class NeighbourThread extends RecursiveAction {
    Vertex tempVertex, endLocation;
    VertexHashMap allVertices;
    int routetype, i;
    PriorityQueue pqOpen;   

    public NeighbourThread(Vertex tempVertex, VertexHashMap allVertices, int routetype, PriorityQueue pqOpen, int i, Vertex endLocation)
    {
        this.allVertices = allVertices;
        this.routetype = routetype;
        this.tempVertex = tempVertex;
        this.pqOpen = pqOpen; 
        this.i = i;
        this.endLocation = endLocation;
    }

    @Override
    public void compute() {
          Edge currentRoad = tempVertex.neighbors.GetItem(i);                             
          Vertex vertexNeighbour = allVertices.GetValue(currentRoad.toid);   

          if (vertexNeighbour.inClosed)//
              return null;   

          if ((!vertexNeighbour.inOpen) || temp_g_score < vertexNeighbour.getTentativeDistance()) 
          {
              vertexNeighbour.from = tempVertex;
              vertexNeighbour.setTentativeDistance(temp_g_score);                                  

              // if neighbor isn't in open set, add it to open set
              if (!vertexNeighbour.inOpen) 
              {
                  vertexNeighbour.inOpen = true;
                  pqOpen.AddItem(vertexNeighbour);
              }
          }
    }

我已经删除了 compute() 中的大部分代码,因为我认为它与问题无关。

我认为问题在于 forkJoinPool.shutdown() 行在已创建的线程完成执行之前被执行。 有什么方法可以确保线程在我循环回到 while 循环的顶部之前完成?

【问题讨论】:

  • 我对您的代码没有深入了解,但是在提出问题时,最好清楚地说明问题所在。我可以推断您的问题是执行任务和关闭时之间存在竞争,但不完全确定。例如“我提交的所有任务都没有被执行”等等......
  • 嗨,John,我想您可能没有阅读我帖子的底部,所以我会对其进行编辑,并确保将问题描述放在顶部!
  • 关于代码质量的旁注:用通用术语(如“计算”)命名一个方法……然后在该单一方法中做许多不同的事情……导致代码难以维护。见这里:java.dzone.com/articles/single-responsibility
  • 我看不到您的任务在哪里执行任何递归。也就是说,只有“主要方法”将任何任务添加到ForkJoinPool。是对的吗?我的意思是,你为什么使用ForkJoinPool 而没有fork()join()

标签: java concurrency fork-join forkjoinpool


【解决方案1】:

我敢打赌,您需要在关闭后在 ForkJoinPool 上awaitTermination。池应在 shutdown 阶段接受并执行所有任务,但不会接受新任务

forkJoinPool.awaitTermination(Integer.MAX_VALUE, TimeUnit.DAYS);

【讨论】:

  • 应该接受并执行所有任务……但不会接受新任务”
【解决方案2】:

你完全在滥用这个框架。您没有进行Data Parallel 处理。正如@erickson 在上述 cmets 中所说,没有递归。

如果 tempVertex.neighbors.GetNoOfItems() 为 1,000 会怎样?您将创建 1,000 个线程,然后关闭框架;在 while (!(pqOpen.IsEmpty())) 等的下一次迭代中创建一个新框架。创建框架需要相当多的开销。创建线程需要更多开销。

我不喜欢批评你的工作,但在不了解所有要求的情况下,我无法为你提供更好的设计(那将是建设性的批评。)

也许你应该研究一个具有线程池结构的阻塞队列。

【讨论】:

    猜你喜欢
    • 2013-05-28
    • 2015-10-13
    • 1970-01-01
    • 2012-01-12
    • 2012-11-24
    • 1970-01-01
    • 2013-07-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多