【问题标题】:java swing concurrency display text in JTextArea with a loopjava swing并发在JTextArea中使用循环显示文本
【发布时间】:2011-05-26 04:27:26
【问题描述】:

我需要执行/显示从 Arraylist 到 JTextArea 的一系列事件,但是,每个事件的执行时间不同。以下是代码,在循环中的第二个事件时失败:

   Thread worker = new Thread(new Runnable()
            {
                public void run()
                {
                    while (eventList.size() > 0)
                        for (Event ev : eventList)
                        if(ev.ready())
                        {
                            /*try
                            {
                                Thread.sleep(1000);
                            } catch (InterruptedException e1)
                            {
                                e1.printStackTrace();
                            }*/
                            jTextArea.append(ev.toString() + "\n");
                            eventList.remove(ev);

                        }
                }
            });
            worker.start();

【问题讨论】:

  • 它“如何?”失败。没有sleep,它会杀死CPU。
  • 可以删除while循环,删除eventList.remove(ev);行

标签: java swing concurrency


【解决方案1】:

我猜你有一个ConcurrentModificationException。尝试使用迭代器,如下所示:

Iterator<Event> it = eventList.iterator();
while(it.hasNext())
{
  Event ev = it.next();
  if (ev.ready())
    it.remove();
}

编辑 为什么会抛出 ConcurrentModificationException?

如果您循环一个集合,直接使用Iterator 或使用for(E : list)并且您修改该集合,通过调用addremove 或类似名称,您将得到这个例外。这试图表明代码中存在问题。问题是,一段代码想要遍历所有对象,而另一段代码添加或删除对象。第一段代码遇到了麻烦,如果集合不断变化,它如何循环所有内容?所以“他们”决定,当您循环访问集合时,您不允许更改集合。 (除非你用你用来循环的迭代器来改变它,就像这段代码那样。it.remove()it 是循环迭代器,因此不会失败。)希望这是有道理的。

【讨论】:

  • 谢谢,你能告诉我为什么Iterator在这里工作而不是arraylist吗?
  • 关键是 List.remove() 与 Iterator.remove() 的使用。 Iterator.remove() 在迭代期间可以安全使用,而 List.remove() 则不是,并且会导致 ConcurrentModificationException。您可能想查看stackoverflow.com/questions/1110404/… 以了解类似问题。
【解决方案2】:

我可能会重复 Lshtar 所说的话,但我会添加一些我自己的东西。其实我是从《J2EE Interview Companion》一书中摘录的。

java.util Collection 类是快速失败的,这意味着如果一个线程更改了一个集合,而另一个线程正在使用迭代器遍历它,则 iterator.hasNext() iterator.next() 调用将抛出 ConcurrentModificationException。甚至同步集合包装类 SynchronizedMapSynchronizedList 也只是有条件的线程安全,这意味着所有单独的操作都是线程安全的但复合的 控制流取决于先前操作的结果的操作可能会遇到线程问题。

解决办法:

使用 ConcurrentHashMapCopyOnWriteArrayListjava.util.concurrent 包)。他们的迭代器提供了更好的可扩展性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-15
    • 2017-09-03
    • 2023-04-08
    相关资源
    最近更新 更多