2010-12-15 116 views
0

我需要执行/显示从Arraylist到JTextArea的一系列事件,但是,每个事件都会在不同的时间执行。JTextArea中的java swing并发显示文本带循环

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(); 
+0

它失败了“如何?”。没有'睡眠'它会杀死CPU。 – khachik 2010-12-15 21:03:58

+0

您可以删除while循环并删除eventList.remove(ev);行 – Enrique 2010-12-15 21:05:03

回答

7

我猜你有一个ConcurrentModificationException:以下是代码,而在回路中的第二个事件失败。尝试使用迭代器,像这样:

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

编辑 为什么会抛出ConcurrentModificationException?

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

+0

谢谢,你能告诉我为什么Iterator在这里工作比arraylist? – Jack 2010-12-15 21:44:03

+0

关键是使用List.remove()和Iterator.remove()。 Iterator.remove()在迭代期间可以安全使用,而List.remove()不是并且会导致ConcurrentModificationException。您可能希望查看http://stackoverflow.com/questions/1110404/remove-elements-from-a-hashset-while-iterating/1115343#1115343以获取类似问题。 – sjlee 2010-12-15 21:56:32

2

我可以重复一下Lshtar说的,但我会添加一些我自己的东西。其实我是从“J2EE Interview Companion”一书中拿出来的。

的java.util中Collection类是快速失败的,这意味着如果一个线程改变的集合,而另一个线程是通过与一个迭代遍历它iterator.hasNext()iterator.next()电话将抛出ConcurrentModificationException。即使是同步收集包装类SynchronizedMapSynchronizedList只是有条件线程安全的,这意味着所有单独的操作都是线程安全的,但是复杂的操作其中控制流取决于先前操作的结果,可能会受到线程问题。

解决方案:

使用的ConcurrentHashMap的CopyOnWriteArrayList的java.util.concurrent封装)。它们的迭代器提供了更好的可伸缩性。