如何创建Synchronized arraylist

我已经像这样创建了synchronized arrayList

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(); } } 

但是像这样得到例外

线程“Thread-1”中的exceptionjava.util.ConcurrentModificationException

我的方法有什么不对吗?

synchronizedList Iterator不是(也不能)同步的,你需要在迭代时手动同步列表(参见javadoc ):

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

另一种方法是使用CopyOnWriteArrayList而不是Collections.synchronizedList() 。 它实现了写时复制语义,因此不需要同步。

其他答案已经确定了问题:

  • 同步集合的迭代器不同步。 实际上,它们只是包装类中的集合对象返回的迭代器。

  • 许多集合类(包括ArrayList )使用故障快速机制来检测迭代期间的并发修改。 这种行为清楚地记录在各个类的javadoc中。 这就是你所看到的。

并非所有集合类都这样做。 例如,许多java.util.Concurrent...集合类允许在迭代期间进行并发修改,但放宽迭代序列的语义,以便修改的结果在迭代器返回的对象中可能显而易见, 也可能不显示。

Collections.synchronizedList()的javadoc解释了如何同步迭代器。 基本上你这样做:

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

(旁白:通常认为做这样的事情会起作用是不安全的。理论上,同步列表可以使用私有锁对象,并且synchronized语句不会锁定并发修改。但是javadocs说这是什么在这种情况下……这样做是安全的。)

这样做的问题是锁定集合会产生潜在的并发瓶颈。 替代方法是使用写入时复制数据结构,该数据结构在内部制作集合相关部分的副本。 这种方法意味着迭代器看到了集合的快照。 可以与迭代同时对集合进行修改,但迭代器不会看到它们。 写时复制的问题在于修改可能要贵得多。

最终,您需要通过并发修改与实际需求来平衡不同集合类型的特征和成本。 你可以逃避迭代器没有看到所有并发修改?

考虑使用线程安全的CopyOnWriteArrayList 。 每次添加项目时,都会创建基础数组的新副本。 但是,迭代器不会反映自迭代器创建以来对列表的添加,但保证不会抛出ConcurrentModificationException

 arrayList=new CopyOnWriteArrayList(); 

在迭代同一集合时操作(添加,删除)集合时会发生java.util.ConcurrentModificationException。

您可能希望在第一个线程创建后创建第二个线程中的创建条目。 因此,您可以使用ArrayLists get( index )和size ()进行控制

正如Spike所说,在迭代它时你无法修改它。 但是,我认为解决方案是在迭代时锁定列表。

 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(); } } 

我不确定你要做什么,所以我希望这不会破坏你的代码的function。

您不能修改正在迭代的Collection。 您可以通过索引访问数组条目而不是通过Iterator来解决此问题。 如果您告诉我您尝试使用此代码解决的问题,我可以提供更多建议。

让我们采用一个正常的列表(由ArrayList类实现)并使其同步。 这显示在SynchronizedArrayList类中。 我们传递Collections.synchronizedList方法一个新的字符串ArrayList。 该方法返回一个同步的字符串列表。 //这里是SynchronizedArrayList类包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 kumarmanoj.mtech@gmail.com * * / public class SynchronizedArrayList {static Logger log = Logger.getLogger(SynchronizedArrayList.class.getName()); public static void main(String [] args){

 List synchronizedList = Collections.synchronizedList(new ArrayList()); 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 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