ConcurrentModificationExceptions возникают, когда вы обращаетесь к одному и тому же списку в двух потоках. Ваша TreeModel, вероятно, использует ArrayLists, Vectors, Hashtables или что-то подобное для хранения узлов.
Я предполагаю, что происходит одна из двух вещей:
1) Ваш TreeModel постоянно запрашивается JTree в потоке EDT при каждом его рендеринге. Это неизбежно и как работает Swing. Если вы обращаетесь к древовидной модели или нижележащим спискам в другом потоке, вы иногда делаете это одновременно с рендерингом, и List вызывает исключение.
2) у вас работают два рабочих свинга, каждый в своих потоках. Они одновременно обновляют / запрашивают список. Та же проблема, что и выше.
Я согласен с Томом, что использование SwingWorker для того, чтобы сделать вашу TreeModel "асинхронной", является очень сложной проблемой, и ее следует избегать. Но, чтобы ответить на ваш вопрос, я бы посмотрел следующий фрагмент кода. Обратите внимание, как все действия по запросу и обновлению дерева выполняются в «готовом» методе, который всегда выполняется в EDT. Я предполагаю, что вы делаете get / sets в методе construct ().
public TreeNode[] getChildren(TreeNode parent){
// Do all normal work you would do
...
// figure out if this parents children have not been fetched yet
boolean needToFetch = ....
if(needToFetch){
worker = new SwingWorker() {
public Object construct() {
// go fetch your children from whatever database, server, file...
// fetchNewChildren must NOT access the TreeModel or any of the underlying
// lists, because you will get a modification exception. This is what
// Tom meant by "Pass a set of arguments into the background thread
// that are not being used in the EDT"
return fetchNewChildNodes(parent);
}
public void finished() {
List<TreeNode> newNodes = (List<TreeNode>)get();
// insert the newly fetched nodes into the parent
// if done correclty, this will fire TreeModelChanged events
// so the tree should re-render, repaint, etc...
parent.addChildren(newNodes);
}
};
worker.start();
}