我有一个在它们之间有依赖关系的任务列表,我正在考虑如何使用JGraphT来管理任务的顺序。我会将图形设置为有向图并在处理它们时删除顶点(或者我应该屏蔽它们?)。如果我一次只执行一个任务,我可以使用TopologicalOrderIterator
,但我希望将任务并行化。我可以获得TopologicalOrderIterator
并检查Graphs.vertexHasPredecessors
,直到我找到尽可能多的执行次数,但理想情况下会有Graphs.getVerticesWithNoPredecessors
之类的内容。我看到Netflix提供了一个实用程序来获取叶子顶点,所以我可以反转图形并使用它,但它可能不值得。谁能指出我更好的方式?谢谢!
答案 0 :(得分:0)
拓扑订单可能不一定是你想要的。这是一个例子,为什么不呢。给定以下任务的拓扑排序:[1,2,3,4]
和弧(1,3)
,(2,3)
。也就是说,任务1
需要在任务3
之前完成,类似于2
和4
。我们还假设任务1
需要很长时间才能完成。因此,我们可以开始并行处理任务1
和2
,但在3
完成之前无法启动1
。即使任务2
完成,我们也无法启动任务4
,因为任务3
是我们排序中的下一个任务,此任务被1
阻止。
这是你能做的。创建一个数组dep[]
,跟踪每个任务的未实现依赖项的数量。因此,dep[i]==0
表示已完成任务i
的所有依赖项,这意味着我们现在可以执行任务i
。如果dep[i]>0
,我们还无法执行任务i
。让我们假设有一个任务j
需要在任务i
之前执行。一旦我们完成任务j
,我们就可以减少任务i
的未实现依赖项的数量,即:dep[i]=dep[i]-1
。同样,如果dep[i]==0
,我们现在可以处理任务i
了。
简而言之,伪代码中的算法看起来像这样:
dep[]
数组。i
dep[i]==0
i
完成,则对依赖于dep[j]
的所有任务j
递减i
。如果任务j
有dep[j]==0
,请开始处理。您当然可以使用定向图来建模依赖关系。每次完成任务时,您都可以简单地遍历传出的邻居(在jgrapht中使用successorsOf(顶点)函数)。 DAG也可以简单地用于检查可行性:如果图形包含一个循环,那么您的依赖项就会出现问题。但是,如果您不需要这种重型机械,我只需创建一个二维数组,其中每个任务i
存储依赖于i
的任务。
结果算法在O(n + m)时间内运行,其中n是任务数,m是弧数(依赖性)。所以这非常有效。