2010-12-15 97 views
0

J'ai besoin d'exécuter/afficher une série d'événements d'un Arraylist à un JTextArea, cependant, chaque événement est exécuté avec un temps différent. Voici le code, il échoue alors en deuxième événement dans la boucle:java swing texte d'accès concurrentiel dans JTextArea avec une boucle

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

Il échoue "comment?". Sans 'dormir', il va tuer le CPU. – khachik

+0

Vous pouvez supprimer la boucle while et supprimer eventList.remove (ev); ligne – Enrique

Répondre

7

Je suppose que vous avez un ConcurrentModificationException. Essayez d'utiliser un itérateur, quelque chose comme ceci:

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

Modifier Pourquoi at-il jeter un ConcurrentModificationException?

Si vous en boucle sur une collection, en utilisant un Iterator directement ou en utilisant for(E : list), et vous modifiez la collection, en appelant add, remove ou similaire, vous obtiendrez cette exception. Cela essaie d'indiquer qu'il y a un problème dans le code. Le problème est qu'un morceau de code veut faire une boucle sur tous les objets, tandis qu'un autre morceau de code ajoute ou supprime des objets. Le premier morceau de code commence à avoir des ennuis, comment peut-il faire une boucle sur tout si la collection ne cesse de changer? Donc 'ils' ont décidé, vous êtes pas autorisés à changer une collection, lorsque vous bouclez dessus. (Sauf si vous le modifiez avec l'itérateur que vous utilisez pour faire une boucle, comme le fait ce code, it.remove(), it est l'itérateur en boucle et n'échoue donc pas.) J'espère que cela a du sens.

+0

merci, pouvez-vous me dire pourquoi Iterator travaille ici que arraylist? – Jack

+0

La clé est l'utilisation de List.remove() par rapport à Iterator.remove(). Iterator.remove() est sûr à utiliser pendant l'itération, alors que List.remove() ne l'est pas et entraîne une exception ConcurrentModificationException. Vous pouvez vérifier http://stackoverflow.com/questions/1110404/remove-elements-from-a-hashset-while-iterating/1115343#1115343 pour une question similaire. – sjlee

2

Je peux répéter ce que Lshtar a dit mais j'ajouterai quelque chose de mon propre. En fait, je l'ai pris dans le livre "J2EE Interview Companion".

Les classes de collecte java.util sont fail-rapide, ce qui signifie que si un thread change une collection tandis qu'un autre fil parcourt à travers avec un iterator la iterator.hasNext() ou iterator.next() appel lancera ConcurrentModificationException. Les classes SynchronizedMap SynchronizedMist et SynchronizedList ne sont thread-safe que conditionnellement, ce qui signifie que toutes les opérations individuelles sont thread-safe mais les opérations composées où le flux de contrôle dépend des résultats des opérations précédentes peuvent être sujettes à des problèmes de threading .

Solution:

utilisation ConcurrentHashMap ou CopyOnWriteArrayList (java.util.concurrent paquet). Leurs itérateurs fournissent une meilleure évolutivité.