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();
2
  • It fails "how?". Without sleep it is going to kill the CPU. Commented Dec 15, 2010 at 21:03
  • You can delete the while loop and delete the eventList.remove(ev); line Commented Dec 15, 2010 at 21:05

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

thanks, can u tell me why Iterator works here than arraylist?
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 stackoverflow.com/questions/1110404/… for a similar question.
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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.