0

I need to execute/display a series of events from a Arraylist to a JTextArea, however, each Event gets execute with different time. Following is the code, it fails while at second Event in the loop:

   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();
Jack
  • 177
  • 4
  • 19

2 Answers2

7

I guess you got a ConcurrentModificationException. Try using an iterator, something like this:

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

Edit Why did it throw a ConcurrentModificationException?

If you loop over a collection, using an Iterator directly or by using for(E : list), and you modify the collection, by calling add, remove or similar, you will get this exception. This tries to indicate there is a problem in the code. The problem is, one piece of code wants to loop over all the objects, while another piece of code adds or removes objects. The first piece of code gets in to trouble, how can it loop over everything if the collection keeps changing? So 'they' decided, you are not allowed to change a collection, when you loop over it. (Unless you change it with the iterator you use to loop, as this code does. it.remove(), it is the looping iterator and thus does not fail.) Hope that makes sense.

Ishtar
  • 11,542
  • 1
  • 25
  • 31
  • thanks, can u tell me why Iterator works here than arraylist? – Jack Dec 15 '10 at 21:44
  • The key is the use of List.remove() vs. Iterator.remove(). Iterator.remove() is safe to use during iteration, whereas List.remove() is not and causes a ConcurrentModificationException. You may want to check out http://stackoverflow.com/questions/1110404/remove-elements-from-a-hashset-while-iterating/1115343#1115343 for a similar question. – sjlee Dec 15 '10 at 21:56
2

I may repeat what Lshtar said but I will add something of my own. Actually I took it from the book "J2EE Interview Companion".

The java.util Collection classes are fail-fast, which means that if one thread changes a collection while another thread is traversing it through with an iterator the iterator.hasNext() or iterator.next() call will throw ConcurrentModificationException. Even the synchronized collection wrapper classes SynchronizedMap and SynchronizedList are only conditionally thread-safe, which means all individual operations are thread-safe but compound operations where flow of control depends on the results of previous operations may be subject to threading issues.

Solution:

Use ConcurrentHashMap or CopyOnWriteArrayList (java.util.concurrent package). Their iterators provide better scalability.

Anton K.
  • 933
  • 3
  • 9
  • 22