how to create Synchronized arraylist
Asked Answered
M

8

14

i have created synchronized arrayList like this

import java.text.SimpleDateFormat;
import java.util.*;


class HelloThread  
{

 int i=1;
 List arrayList;
  public  void go()
  {
 arrayList=Collections.synchronizedList(new ArrayList());
 Thread thread1=new Thread(new Runnable() {

  public void run() {
  while(i<=10)
  {
   arrayList.add(i);
   i++;
  }
  }
 });
 thread1.start();
 Thread thred2=new Thread(new Runnable() {
  public void run() {
     while(true)
     {
   Iterator it=arrayList.iterator();
      while(it.hasNext())
      {
       System.out.println(it.next());
      }
     }
  }
 });
 thred2.start();
  }
 }

public class test
{
  public static void main(String[] args)
  {
   HelloThread hello=new HelloThread();
   hello.go();
  }
}

but getting exception like this

Exception in thread "Thread-1" java.util.ConcurrentModificationException

anything wrong in my approach ?

Macrogamete answered 28/9, 2010 at 15:24 Comment(0)
C
28

Iterator of synchronizedList is not (and can't be) synchronized, you need to synchronize on the list manually while iterating (see javadoc):

synchronized(arrayList) {
    Iterator it=arrayList.iterator(); 
    while(it.hasNext()) { 
        System.out.println(it.next()); 
   } 
}

Another approach is to use a CopyOnWriteArrayList instead of Collections.synchronizedList(). It implements a copy-on-write semantic and therefore doesn't require synchronization.

Coppola answered 28/9, 2010 at 15:30 Comment(0)
L
12

Consider using a CopyOnWriteArrayList which is thread-safe. Every time you add an item, a fresh copy of the underlying array is created. However, the iterator will not reflect additions to the list since the iterator was created, but is guaranteed not to throw ConcurrentModificationException.

arrayList=new CopyOnWriteArrayList();
Legator answered 28/9, 2010 at 15:41 Comment(1)
It should be noted that the copying process copies the element references for all of the list elements. This scales poorly for long lists.Pathogen
P
12

Other answers have identified the problem:

  • The iterators for synchronized collections are not synchronized. In fact, they are simply the iterators returned by the collection objects inside the wrapper classes.

  • Many collection classes (including ArrayList) use a fail-fast mechanism to detect concurrent modifications during iteration. This behavior is clearly documented in the javadocs for the respective classes. This is what you are seeing.

Not all collection classes do this. For example, many of the java.util.Concurrent... collection classes allow concurrent modification during iteration, but relax the semantics of the iteration sequence so that the results of the modifications may or may not be apparent in the objects returned by the iterator.

The javadoc for the Collections.synchronizedList() explains how to synchronize the iterator. Basically you do this:

List list = Collections.synchronizedList(new ArrayList());
  ...
synchronized (list) {
    Iterator i = list.iterator(); // Must be in synchronized block
    while (i.hasNext())
        foo(i.next());
}

(Aside: normally it is not safe to assume that doing something like this would work. In theory, the synchronized list could use a private lock object, and the synchronized statement would not lock out concurrent modifications. However the javadocs say that this is what to do in this case ... so it is safe.)

The problem with doing that is that locking the collection creates a potential concurrency bottleneck. The alternative to is to use a copy-on-write data structure that internally makes a copy of the relevant parts of the collection. This approach means that an iterator sees sees a snapshot of the collection. Modifications may be made to the collection concurrent with an iteration, but the iterator does not see them. The problem with copy-on-write is that modifications are potentially a lot more expensive.

Ultimately, you need to balance the characteristics and costs of the different collection types wrt concurrent modification versus your actual requirements. Can you get away with the iterator not seeing all concurrent modifications?

Pathogen answered 28/9, 2010 at 15:46 Comment(0)
C
3

The java.util.ConcurrentModificationException occurs when you manipulate (add,remove) a collection while iterating over the same collection.

You probably want to consume the create entries in your second thread while after they have been created by your first thread. So you could use ArrayLists get( index ) and size() for control

Cammiecammy answered 28/9, 2010 at 15:33 Comment(0)
G
2

As Spike said, you can't modify a collection while iterating it. However, I think the solution is to lock the list while iterating.

class HelloThread  
{

 int i=1;
 List arrayList;
  public  void go()
  {
 arrayList=Collections.synchronizedList(new ArrayList());
 Thread thread1=new Thread(new Runnable() {

  public void run() {
  while(i<=10)
  {
synchronized(someLock) {
   arrayList.add(i);
}
   i++;
  }
  }
 });
 thread1.start();
 Thread thred2=new Thread(new Runnable() {
  public void run() {
     while(true)
     {
synchronized(someLock) {
   Iterator it=arrayList.iterator();
      while(it.hasNext())
      {
       System.out.println(it.next());
      }
}
     }
  }
 });
 thred2.start();
  }
 }

public class test
{
  public static void main(String[] args)
  {
   HelloThread hello=new HelloThread();
   hello.go();
  }
}

I'm not sure what you're trying to do, so I hope this doesn't break the functionality of your code.

Glanders answered 28/9, 2010 at 15:33 Comment(0)
G
0

You may not modify a Collection that you are iterating. You can work around this by accessing the array entries by index, not through an Iterator. I can provide more advice if you tell me the problem that you are trying to solve with this code.

Gabbie answered 28/9, 2010 at 15:28 Comment(1)
i can get your point i can't use iterator to access the synchronized arrayList.Macrogamete
A
0

Let's take a normal list (implemented by the ArrayList class) and make it synchronized. This is shown in the SynchronizedArrayList class. We pass the Collections.synchronizedList method a new ArrayList of Strings. The method returns a synchronized List of Strings. //Here is SynchronizedArrayList class package com.mnas.technology.automation.utility; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.apache.log4j.Logger; /** * * @author manoj.kumar * @email [email protected] * */ public class SynchronizedArrayList { static Logger log = Logger.getLogger(SynchronizedArrayList.class.getName()); public static void main(String[] args) {

List<String> synchronizedList = Collections.synchronizedList(new ArrayList<String>());
synchronizedList.add("Aditya");
synchronizedList.add("Siddharth");
synchronizedList.add("Manoj");

// when iterating over a synchronized list, we need to synchronize access to the synchronized list
synchronized (synchronizedList) {
Iterator<String> iterator = synchronizedList.iterator();
while (iterator.hasNext()) {
log.info("Synchronized Array List Items: " + iterator.next());
}
}

}
}

Notice that when iterating over the list, this access is still done using a synchronized block that locks on the synchronizedList object. 
In general, iterating over a synchronized collection should be done in a synchronized block
Arthro answered 7/1, 2015 at 6:2 Comment(0)
P
0

ArrayList is non-synchronized collection and should not be used in concurrent environment without explicit synchronization. To synchronize ArrayList, we can use two methods provided by JDK

  • Collections.synchronizedList() method – It returns synchronized list backed by the specified list. It is recommended that we should manually synchronize on the returned list when traversing it via Iterator, Spliterator or Stream. Else it may result in non-deterministic behavior. No explicit synchronization is needed to add, remove elements from synchronized arraylist
  • CopyOnWriteArrayList class – It is a thread-safe variant of ArrayList.

Since you are using iterator without explicit synchronization you are getting the error

Philipines answered 20/11, 2021 at 1:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.