Многопоточная обработка JTree
Есть следующий класс, реализующий интерфейс Runnable:
public class TreeHandler implements Runnable {
private String name;
private JTree tree;
private Tree model;
public TreeHandler(String name, JTree tree) {
this.name = name;
this.tree = tree;
model = (Tree)tree.getModel();
}
@Override
public void run() {
Node node;
String nodeName;
int nodeNum;
System.out.println(name + " started");
while (true) {
System.out.println(name + " want to find node for handling");
synchronized (tree) {
while (true) {
Node root = (Node)(model.getRoot());
if (root == null || !isNumber(root)) {
System.out.println(name + " ended job");
return;
}
System.out.println(name + " get tree and searching...");
node = model.findNode(root, tester);
if (node != null)
break;
System.out.println("For that time there are no nodes, " + name + " waiting...");
try {
tree.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(name + " found node " + node);
nodeName = node.toString();
nodeNum = Integer.parseInt(nodeName);
model.setData(node, this.name + " start with " + nodeName);
updateTree();
}
System.out.println(name + " handling " + nodeName);
nodeNum = (int)(nodeNum > 47 ? 47-Math.random() * 7 : nodeNum < 20 ? 20 : nodeNum);
fibo(nodeNum);
System.out.println(name + " handled " + nodeName);
synchronized (tree) {
model.setData(node, name + " finished with " + nodeName);
updateTree();
tree.notifyAll();
}
}
}
private boolean isNumber(Object node) {
try {
Integer.parseInt(node.toString());
return true;
} catch (Exception e) {
return false;
}
}
public boolean isFinished(Object node) {
return node.toString().indexOf("finish") >= 0;
}
public int fibo(int n) {
if (n <= 0)
return 0;
else if (n == 1 || n == 2)
return n;
else
return fibo(n-1) + fibo(n-2);
}
Predicate<Node> tester = (node)->{
if (!isNumber(node))
return false;
Iterator<Node> itr = model.iterator(node);
itr.next();
while (itr.hasNext()) {
if (!isFinished(itr.next()))
return false;
}
return true;
};
void updateTree() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
tree.updateUI();
}
});
}
}
Данный код предназначается для демонстрировации работы многопоточности в Java. Но, насколько я понимаю, блок synchronized(tree)
указывает на то, что компонент JTree будет обрабатываться только одним потоком в один момент времени, что в данном случае исключает целесообразность применения нескольких потоков для обработки данного дерева. Можно ли как-то изменить данный код, чтобы synchronized
или его аналог ограничивал доступ одного потока только к одному узлу, а не ко всему дереву в целом?
Источник: Stack Overflow на русском