java多线程与并发之java并发编程实践(十)

来源:互联网 发布:网络歌手rocky是谁 编辑:程序博客网 时间:2024/05/16 15:23
并发集合(三)
----------
CopyOnWriteArrayList和CopyOnWriteArraySet

这两个集合对copy-on-write模式作了比较好的支持。这个模式说明了,为了维护对象的一致性快照,要依靠不可变性来消除在协调读取不同的但是相关的属性时需要的同步。
对于集合,这意味着如果有大量的读(即get())和迭代,不必进行同步操作以照顾偶尔的写(即add())调用。对于新的CopyOnWriteArrayList和CopyOnWriteArraySet类,所有可变的操作都首先取得后台数组的副本,对副本进行更改,然后替换副本。这种做法保证了在遍历自身可更改的集合时,永远不会抛出ConcurrentModificationException。遍历集合会用原来的集合完成,而在以后的操作中使用更新后的集合。这些新的集合最适合于读操作通常大大超过写操作的情况。集合的使用与它们的非copy-on-write替代物完全一样。只是创建集合并在其中加入或删除元素。即使对象加入到了集合中,原来的Iterator也可以进行,继续遍历原来集合中的项。

下面是使用copy-on-write集合和一般类型集合时进行遍历的例子:

package copyonwrite;import java.util.ArrayList;import java.util.Arrays;import java.tuil.ConcurrentModificationException;import java.util.Iterator;import java.util.List;import java.util.concurrent.CopyOnWriteArrayList;public class CopyOnWriteDemo{public static void main(String[] args){String[] ss = {"aa","bb","cc"};List list1 = new CopyOnWriteArrayList(Arrays.asList(ss));List list2 = new ArrayList(Arrays.asList(ss));Iterator itor1 = list1.iterator();Iterator itor2 = list2.iterator();list1.add("New");list2.add("New");try{printAll(itor1);}catch(ConcurrentModificationException e){System.err.println("Shouldn't get here");}try{printAll(itor2);}catch(ConcurrentModificationException e){System.err.println("Will get here.ConcurrentModificationException occurs!");}}private static void printAll(Iterator itor){while(itor.hasNest()){System.out.println(itor.next());}}}
运行结果如下:
Will get here.ConcurrentModificationException occurs!
aa
bb
cc
这个示例程序创建CopyOnWriteArrayList和ArrayList这两个实例。在得到每一个实例的Iterator后,分别在其中加入一个元素。当ArrayList迭代因一个ConcurrentModificationException问题而立即停止时,CopyOnWriteArrayList迭代可以继续,不会抛出异常,因为原来的集合是在得到iterator之后改变的。如果这种行为(比如通知原来一组事件监听器中的所有元素)是您需要的,那么最好使用copy-on-write集合。如果不使用的话,就还用原来的,并保证在出现异常时对它进行处理。