查看“集合与同步集合的比较”的源代码
←
集合与同步集合的比较
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
[[category:Java]] == 关于集合、同步集合 == 集合框架中的集合、映射,一般都不是线程安全的,而实现线程安全也有几种方式。 == List === List相关的有: # Vector:线程安全(但不推荐使用); # ArrayList、LinkedList:线程不安全; # SynchronizedList:线程安全,Collections子类实现; # CopyOnWriteArrayList:线程安全,采用修改copy的方法解决同步问题; === 为什么不推荐 Vector(和Stack) === *(Stack 继承于 Vector) 因为: # 对于不需要同步的场景:ArrayList和Vector操作没有区别,但没有锁开销; # 对于需要同步的场景:Vector 对操作方法加锁,却没有对迭代器操作加锁; #: 通常需要同步一个整个序列的操作,同步单个操作是不安全的。 #: 如:在Vector上进行迭代操作,仍然需要手动加一个锁,以避免其他人同时更改集合,否则将导致“ConcurrentModificationException”; === SynchronizedList 与 CopyOnWriteArrayList === 二者主要区别在于实现 # 同步的方式不一样(操作加锁;修改复制、操作加锁); # 使用的锁不一样(内部锁、ReentrantLock); # 迭代器方法是否同步; SynchronizedList 部分源码: <syntaxhighlight lang="java"> public int indexOf(Object o) { synchronized (mutex) {return list.indexOf(o);} } public int lastIndexOf(Object o) { synchronized (mutex) {return list.lastIndexOf(o);} } public boolean addAll(int index, Collection<? extends E> c) { synchronized (mutex) {return list.addAll(index, c);} } public ListIterator<E> listIterator() { return list.listIterator(); // Must be manually synched by user } public ListIterator<E> listIterator(int index) { return list.listIterator(index); // Must be manually synched by user } </syntaxhighlight> 由源码可以看出: * synchronizedList是将List集合作为参数来创建的synchronizedList集合; * 采用内部锁('''synchronized''')的方法,所开销大(依赖于Java版本对synchronized优化了); * 迭代器(ListIterator)方法却没有加锁处理; CopyOnWriteArrayList 部分源码: <syntaxhighlight lang="java"> /** The array, accessed only via getArray/setArray. */ private volatile transient Object[] array;//保证了线程的可见性 public void add(int index, E element) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; if (index > len || index < 0) throw new IndexOutOfBoundsException("Index: "+index+ ", Size: "+len); Object[] newElements; int numMoved = len - index; if (numMoved == 0) newElements = Arrays.copyOf(elements, len + 1); //copy一份比当前数组长度+1的array数组 else { newElements = new Object[len + 1]; //将add的参数赋值 System.arraycopy(elements, 0, newElements, 0, index); System.arraycopy(elements, index, newElements, index + 1, numMoved); } newElements[index] = element; setArray(newElements); //将原数组指向新的数组 } finally { lock.unlock(); } } public E remove(int index) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; E oldValue = get(elements, index); int numMoved = len - index - 1; if (numMoved == 0) setArray(Arrays.copyOf(elements, len - 1)); //copy一份比当前数组长度-1的array数组 else { Object[] newElements = new Object[len - 1]; System.arraycopy(elements, 0, newElements, 0, index); System.arraycopy(elements, index + 1, newElements, index, numMoved); setArray(newElements); //将原数组指向新的数组 } return oldValue; } finally { lock.unlock(); } } /** * 将原数组指向新的数组 */ final void setArray(Object[] a) { array = a; } </syntaxhighlight> 由其源码可以看出: :执行add方法和remove方法的时候,分别创建了一个当前数组长度+1和-1的数组,将数据copy到新数组中,然后执行修改操作。修改完之后调用setArray方法来指向新的数组。 * 使用'''ReentrantLock'''可重入锁来保证同步; * 并且使用volatile修饰数组来保证修改后的可见性; * 其迭代器(实现了Iterator的内部类COWIterator)方法也实现了同步(依旧采用 ReentrantLock); == Map ==
返回至“
集合与同步集合的比较
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
大陆简体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
笔记
服务器
数据库
后端
前端
工具
《To do list》
日常
阅读
电影
摄影
其他
Software
Windows
WIKIOE
所有分类
所有页面
侧边栏
站点日志
工具
链入页面
相关更改
特殊页面
页面信息