Tree 遍历无序二叉树
我需要以并行方式访问树。Tree 遍历无序二叉树,tree,parallel-processing,Tree,Parallel Processing,我需要以并行方式访问树。 怎么可能呢?如果没有递归,我无法在树中想到任何东西。不确定您是否仍在寻找关于此问题的答案,但我认为其他人可能会受益 您仍然可以使用递归,但您需要锁定树的分支,并允许其他线程“跳过”这些分支,因为它们已经在或已经被处理 例如,假设您正在处理一棵树,进行广度优先遍历,因此在递归方法的每次运行中,您都要遍历当前节点的子节点。每个线程必须遍历当前节点的子节点,并尝试锁定每个子节点,如果已经锁定,则跳过该子节点 我不确定您使用的是什么树实现,所以您应该将下面示例代码中的“Node
怎么可能呢?如果没有递归,我无法在树中想到任何东西。不确定您是否仍在寻找关于此问题的答案,但我认为其他人可能会受益 您仍然可以使用递归,但您需要锁定树的分支,并允许其他线程“跳过”这些分支,因为它们已经在或已经被处理 例如,假设您正在处理一棵树,进行广度优先遍历,因此在递归方法的每次运行中,您都要遍历当前节点的子节点。每个线程必须遍历当前节点的子节点,并尝试锁定每个子节点,如果已经锁定,则跳过该子节点 我不确定您使用的是什么树实现,所以您应该将下面示例代码中的“Node”对象视为伪代码,但其余的都是正确的Java 在下面的示例中,选择了一个预定的深度来应用锁定-这确保了线程不会简单地锁定在树的根上,而是序列化对整个树的访问 选择正确的深度取决于特定树的形状。例如,如果它是一个二叉树,那么您的树在深度3处可能有多达8个分支,这对于几个线程来说是最好的,但是如果您运行20个线程,则需要选择一个较低深度的序列化点,以确保所有线程都能够处理某个分支 您还可以使用其他一些方法来决定何时锁定,例如,如果节点可以有效地报告它有多少叶节点,您可以设置阈值,重要的是所有线程使用相同的代码来决定是否锁定
Object master_LOCK = new Object();
HashMap locks = new HashMap();
int DEPTH = 5;
public boolean lockNode(Object nodeID) {
synchronized(master_LOCK) {
Object node_LOCK = (Object)locks.get(nodeID);
if (node_LOCK == null) {
//we can lock this node
locks.put(nodeID,new Object());
return true;
} else {
//node already locked
return false;
}
}
}
public void traverseBreadhFirst(Node node) {
locks.clear();
traverseBreadthFirst(node,0);
}
public void traverseBreadthFirst(Node node, int currentDepth) {
currentDepth++;
//Process the current node here
//Iterate through children, locking to force serialised access only at a predetermined depth
List children = node.getChildren();
for (int i = 0; i < children.size(); i++) {
Node child = (Node)children.get(i);
//If we are a certain depth in the tree we start serialising access from that point on
//This ensures that there are enough branches at this point to roughly evenly distribute them
//to all available threads.
if (currentDepth < DEPTH ) {
//All threads are to go to depth N
traverseBreadthFirst(node,currentDepth);
} else if (currentDepth == DEPTH ) {
//At depth N we lock all branches we intend to process
if (lockNode(child.getID())) {
//We have locked this child node so we should process it
traverseBreadthFirst(node,currentDepth);
} else {
//This child has been locked for processing already so we skip it
}
} else {
//We are deeper than depth N so we can traverse our locked branch without locking further
traverseBreadthFirst(node,currentDepth);
}
}
}