2010-12-15 115 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封裝)。它們的迭代器提供了更好的可伸縮性。