`
chenzehe
  • 浏览: 538123 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Java 并发集合CopyOnWriteArrayList

 
阅读更多

1、Java在JDK1.5之前基本上对所有集合都实现了线程同步版本synchronized*,用集合工具类Collections即可得到,如下都为Collections中的方法:

static <T> Collections<T> 
 synchronizedCollection(Collection<T> c) 
          返回指定 collection 支持的同步(线程安全的)collection。 
static <T> List<T> 
 synchronizedList(List<T> list) 
          返回指定列表支持的同步(线程安全的)列表。 
static <K,V> Map<K,V> 
 synchronizedMap(Map<K,V> m) 
          返回由指定映射支持的同步(线程安全的)映射。 
static <T> Set<T> 
 synchronizedSet(Set<T> s) 
          返回指定 set 支持的同步(线程安全的)set。 
static <K,V> SortedMap<K,V> 
 synchronizedSortedMap(SortedMap<K,V> m) 
          返回指定有序映射支持的同步(线程安全的)有序映射。 
static <T> SortedSet<T> 
 synchronizedSortedSet(SortedSet<T> s) 
          返回指定有序 set 支持的同步(线程安全的)有序 set。 

其内部实现是在内部维护一个对应的集合类型,然后相应所有的操作都加上同步关键字synchronized,同步方法内再调用内部集合的方法,如下为synchronizedMap的实现:

private static class SynchronizedMap<K,V>
	implements Map<K,V>, Serializable {
        private final Map<K,V> m;     // Backing Map
        final Object      mutex;
	SynchronizedMap(Map<K,V> m) {
            if (m==null)
                throw new NullPointerException();
            this.m = m;
            mutex = this;
        }
	public V get(Object key) {
	    synchronized(mutex) {return m.get(key);}
        }

	public V put(K key, V value) {
	    synchronized(mutex) {return m.put(key, value);}
        }
        ......
}

 

 2、传统方式下的Collection在迭代集合时,不允许对集合进行修改,如下代码会抛出ConcurrentModificationException异常:

Collection<String> users = new ArrayList<String>();
users.add("first");
users.add("second");
users.add("third");
Iterator<String> itrUsers = users.iterator();
while (itrUsers.hasNext()) {
	String user = itrUsers.next();
	if ("first".equals(user)) {
		users.remove(user);
	}
	System.out.println(user);
}

 在调用next()方法时,由于删除了元素导致期望长度和实现长度不一至而抛出异常:

	public E next() {
            checkForComodification();
	    try {
		E next = get(cursor);
		lastRet = cursor++;
		return next;
	    } catch (IndexOutOfBoundsException e) {
		checkForComodification();
		throw new NoSuchElementException();
	    }
	}
	final void checkForComodification() {
	    if (modCount != expectedModCount)
		throw new ConcurrentModificationException();
	}
    }

 把上面ArrayList换成CopyOnWriteArrayList即可完成在迭代中对集合进行操作,并且在多线程中也是安全的:

Collection<String> users = new CopyOnWriteArrayList<String>();

 

 3、CopyOnWriteArrayList是在Java JDK1.5中引入的并发类,在java.util.concurrent包下,它是ArrayList 的一个线程安全的变体,并且是在读时无锁的ArrayList:

    public E get(int index) {
        return (E)(getArray()[index]);
    }

 此方法很简单没有加锁,有可能会出现脏读的情况,但是性能非常高,对于写少读多且对脏数据要求不严的场景可以使用。

构造方法:

    public CopyOnWriteArrayList() {
        setArray(new Object[0]);
    }

 与ArrayList不同,CopyOnWriteArrayList创建一个大小为0的数组。

add(E)方法:add方法并没有使用内置锁,而是使用JDK1.5提供的显示锁ReentrantLock来保证线程的安全的:

    public boolean add(E e) {
	final ReentrantLock lock = this.lock;
	lock.lock();
	try {
	    Object[] elements = getArray();
	    int len = elements.length;
	    Object[] newElements = Arrays.copyOf(elements, len + 1);
	    newElements[len] = e;
	    setArray(newElements);
	    return true;
	} finally {
	    lock.unlock();
	}
    }

 此处和ArrayList不同的是每次都创建一个新的Object数组,此数据的大小为当前数据大小加1,将之前的数组中的内容复制到新的数组中,并将新增加的对象放入到数组的末尾,最后把新数组的引用赋值给全局的数组对象:

    final void setArray(Object[] a) {
        array = a;
    }

 

 remove(Object)方法:和add方法一样,删除元素方法也采用JDK1.5的加锁方式来保证线程安全,但它和ArrayList采用的删除方法不同,它是创建一个长度比当前数组小1的新数组,然后遍历老数组,其它元素全部加到新数组,最后把新数组的引用赋值给全局的数组对象,它并没有使用System的arrayCopy来实现,可能会导致性能一定的下降。

 

iterator()迭代:调用iterator方法后创建一个新的COWIterator实例,并保存了一个当前数组的快照,在调用next遍历时仅对快照进行遍历,所以在迭代CopyOnWriteArrayList中操作其中元素不会像ArrayList一样抛出ConcurrentModificationException异常:

    public Iterator<E> iterator() {
        return new COWIterator<E>(getArray(), 0);
    }

 

 4、和ArrayList性能比较

单线程:在元素较少的情况下,两个类的性能基本上一至,但是到元素很多时,CopyOnWriteArrayList增加元素的删除元素性能会差一点

多线程:随着元素数量和线程数量的增加,CopyOnWriteArrayList在增加和删除元素的性能就会下降,而且比ArrayList性能低。但在查找元素时随着元素数量和线程数量的增加性能比ArrayList好。

在读多写少的并发场景中,CopyOnWriteArrayList比ArrayList是更好的选择。

 

 

 

分享到:
评论

相关推荐

    java并发集合

    在深入学习Java并发集合时,我们需要理解每个类的内部实现机制,如ConcurrentHashMap的分段锁,CopyOnWriteArrayList的写时复制策略,以及各种同步工具类的工作原理。同时,了解何时以及如何选择合适的并发集合也是...

    java集合-CopyOnWriteArrayList的使用

    在Java中,CopyOnWriteArrayList(写入时复制数组列表)是线程安全的集合类,它实现了List接口,并使用了"写入时复制"的策略来保证线程安全性。 CopyOnWriteArrayList的主要特点是:在进行修改操作(例如添加、修改...

    java并发编程实战源码,java并发编程实战pdf,Java

    5. **并发集合**:Java的并发集合类库,如ConcurrentHashMap、CopyOnWriteArrayList、ConcurrentLinkedQueue等,为并发环境下高效、安全的数据共享提供了支持。 6. **原子操作与CAS**:AtomicInteger、AtomicLong等...

    java并发编程艺术

    并发集合是Java并发编程中的重要组成部分,如`ConcurrentHashMap`, `CopyOnWriteArrayList`, `ConcurrentLinkedQueue`等,它们设计为线程安全,能够在并发环境中高效地工作。书中的章节可能会详细解释这些集合的设计...

    java并发编程2

    以上知识点覆盖了Java并发编程的主要方面,包括线程管理、同步机制、并发工具、设计模式、并发集合以及并发编程的最佳实践等,是理解和掌握Java并发编程的关键。在实际开发中,理解和熟练运用这些知识可以编写出高效...

    java 并发编程的艺术pdf清晰完整版 源码

    Java语言提供了丰富的并发工具和API,如线程、守护线程、线程池、同步机制(synchronized、wait/notify)、并发集合(ConcurrentHashMap、CopyOnWriteArrayList等)以及并发框架(ExecutorService、Future、Callable...

    《java 并发编程实战高清PDF版》

    最后,书中还涵盖了并发集合框架,如`ConcurrentHashMap`,它在并发环境下提供了高效且线程安全的存储解决方案。还有`CopyOnWriteArrayList`和`CopyOnWriteArraySet`,它们在读多写少的场景下表现出色。 总之,...

    Java 并发编程实战.pdf

    - **并发集合**:如ConcurrentHashMap、CopyOnWriteArrayList等,这些集合类针对多线程环境进行了优化,能够在保证线程安全的同时提高性能。 - **线程通信**:包括线程间的同步、等待、通知等机制,是实现复杂并发...

    java并发编程实战(英文版)

    - **并发集合**:详细介绍Java提供的各种并发集合类,如`ConcurrentHashMap`、`CopyOnWriteArrayList`等,并讨论它们适用的场景和优缺点。 #### 四、案例分析 书中通过大量的实际案例分析,帮助读者更好地理解并发...

    JAVA并发编程艺术pdf版

    5. **并发集合**: - **线程安全的集合**:如Vector、ConcurrentHashMap和CopyOnWriteArrayList等,它们在内部实现了同步机制,保证了并发访问的安全性。 - **并发容器框架**:如BlockingQueue(阻塞队列),常...

    深入解析Java中的CopyOnWriteArrayList:工作原理与应用

    在Java的并发编程中,CopyOnWriteArrayList 是一个重要的线程安全集合类,它通过写时复制(Copy-On-Write)机制实现了高效的读操作。本文将详细探讨 CopyOnWriteArrayList 的工作原理、优缺点、适用场景以及代码示例...

    Java并发编程常识-梁飞.rar

    Java并发集合,如ConcurrentHashMap、CopyOnWriteArrayList等,设计时考虑了并发性能,能够在不加锁的情况下提供线程安全的访问。这些集合内部实现了复杂的同步策略,提高了并发效率。 并发工具类,如...

    JAVA并发编程实践.pdf+高清版+目录 书籍源码

    此外,书中还介绍了Java并发容器,如ConcurrentHashMap、CopyOnWriteArrayList和BlockingQueue等,这些都是为并发环境设计的高效数据结构。它们在多线程环境下的性能和线程安全特性使得开发者能更方便地实现并发操作...

    java并发编程与实践

    4. **并发集合**:Java并发包提供了线程安全的集合实现,如ConcurrentHashMap、CopyOnWriteArrayList和BlockingQueue等。这些集合在多线程环境中能保证数据一致性。 5. **死锁、活锁和饥饿**:文档可能会介绍这些...

    java并发编程实践pdf笔记

    - **并发集合** 如`ConcurrentHashMap`、`CopyOnWriteArrayList`等,它们在内部实现了线程安全的算法,可以在并发环境中高效使用。 7. **活锁与死锁** - **活锁** 发生在线程间不断地尝试但无法取得进展的情况,...

    ( Java并发程序设计教程.zip )高清版 PDF

    此外,Java并发集合框架是另一个重要章节。它包含一系列优化过的线程安全容器,如ConcurrentHashMap、CopyOnWriteArrayList等,这些容器提供了高效且线程安全的并发操作。了解它们的工作原理和使用场景对于编写高...

    java并发实战中文文档

    4. **并发集合**:Java并发集合如`ConcurrentHashMap`、`CopyOnWriteArrayList`和`ConcurrentLinkedQueue`等,是为并发环境优化过的数据结构。它们内部实现了线程安全,能够在不引入全局锁的情况下实现高效并发操作...

Global site tag (gtag.js) - Google Analytics