我已经实现了一种管道方法。我将遍历一棵树,我需要一些事先不可用的值...因此,我必须并行(或之前)遍历树,并为每个要保存值的节点(例如descendantCount)再次遍历一次。
因此,我对树进行了遍历,然后从构造函数中调用了一个方法,该方法调用了一个通过ExecutorService启动的新线程。提交的Callable为:
@Override
public Void call() throws Exception {
// Get descendants for every node and save it to a list.
final ExecutorService executor =
Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
int index = 0;
final Map<Integer, Diff> diffs = mDiffDatabase.getMap();
final int depth = diffs.get(0).getDepth().getNewDepth();
try {
boolean first = true;
for (final AbsAxis axis = new DescendantAxis(mNewRtx, true); index < diffs.size()
&& ((diffs.get(index).getDiff() == EDiff.DELETED && depth < diffs.get(index).getDepth()
.getOldDepth()) || axis.hasNext());) {
if (axis.getTransaction().getNode().getKind() == ENodes.ROOT_KIND) {
axis.next();
} else {
if (index < diffs.size() && diffs.get(index).getDiff() != EDiff.DELETED) {
axis.next();
}
final Future<Integer> submittedDescendants =
executor.submit(new Descendants(mNewRtx.getRevisionNumber(), mOldRtx
.getRevisionNumber(), axis.getTransaction().getNode().getNodeKey(), mDb
.getSession(), index, diffs));
final Future<Modification> submittedModifications =
executor.submit(new Modifications(mNewRtx.getRevisionNumber(), mOldRtx
.getRevisionNumber(), axis.getTransaction().getNode().getNodeKey(), mDb
.getSession(), index, diffs));
if (first) {
first = false;
mMaxDescendantCount = submittedDescendants.get();
// submittedModifications.get();
}
mDescendantsQueue.put(submittedDescendants);
mModificationQueue.put(submittedModifications);
index++;
}
}
mNewRtx.close();
} catch (final AbsTTException e) {
LOGWRAPPER.error(e.getMessage(), e);
}
executor.shutdown();
return null;
}因此,对于每个节点,它都创建了一个新的Callable,它遍历每个节点的树,并计算子代和修改(我实际上是将两个树的修订融合在一起)。好吧,mDescendantsQueue和mModificationQueue是BlockingQueues。起初,我只有descendantsQueue,并再次遍历树以获得每个节点的修改(计算在当前节点的子树中所做的修改)。然后我想为什么不同时做这两件事,并实现流水线方法。遗憾的是,每次我实现另一个多线程“步骤”时,性能似乎都会下降。
也许是因为XML树通常不是那么深,并且并发开销太大:-/
起初,我按顺序执行所有操作,这是最快的:-遍历树-对于每个节点遍历子节点并计算descendantCount和modificationCount
在使用BlockingQueues的流水线方法后,性能似乎有所下降,但实际上我没有做任何时间测量,而且我必须恢复许多更改才能返回:(也许随着Core2Duo的增加,性能会提高,因为我现在只有一个CPU用于测试。
诚挚的问候,
约翰尼斯
发布于 2011-09-09 22:49:00
这可能会有所帮助:Amadahl's law,它基本上说明了生产率的提高取决于(与之成反比)必须由同步处理的代码的百分比。因此,即使通过增加更多的计算资源来增加,也不会得到更好的结果。理想情况下,如果(同步部分与总部分的比率)较低,则使用(处理器数量+1)应提供最佳输出(除非您正在使用网络或其他I/O,在这种情况下,您可以增加池的大小)。因此,只需从上面的链接中跟踪它,看看是否有帮助
发布于 2011-09-09 21:10:24
从您的描述中,听起来像是在递归地创建线程,每个线程处理一个节点,然后产生一个新线程?这是正确的吗?如果是这样的话,我对你的性能下降并不感到惊讶。
一个简单的递归下降方法实际上可能是实现这一点的最佳方法。我看不出多线程在这里会给你带来什么好处。
https://stackoverflow.com/questions/7362035
复制相似问题