JUC源码分析24-队列-CopyOnWriteArrayList,CopyOnWriteArraySet
来源:互联网 发布:歼31黑烟知乎 编辑:程序博客网 时间:2024/05/18 05:02
在看LinkedTransferQueue之前看个简单点的CopyOnWriteArrayList。CopyOnWriteArrayList还是比较简单的,内部结构只有一个数组和一把锁。采用写时加锁复制数组,所有的可变操作都在新数组上进行,读则是老数组,有点读写分离意思,比ArrayList都加锁开肯定好的多,感觉适合那种读多写少的场景。
内部结构只有一个重入锁,一个数组:
<span style="font-size:18px;">/** The lock protecting all mutators */transient final ReentrantLock lock = new ReentrantLock();/** The array, accessed only via getArray/setArray. */private volatile transient Object[] array;/** * Gets the array. Non-private so as to also be accessible * from CopyOnWriteArraySet class. */final Object[] getArray() { return array;}/** * Sets the array. */final void setArray(Object[] a) { array = a;}/** * Creates an empty list. */public CopyOnWriteArrayList() { setArray(new Object[0]);}public int size() { return getArray().length;}/** * Returns <tt>true</tt> if this list contains no elements. * * @return <tt>true</tt> if this list contains no elements */public boolean isEmpty() { return size() == 0;}</span>
CopyOnWriteArrayList的get等获取的方法都是对数组的基本操作,没有什么新意:
<span style="font-size:18px;">private static int indexOf(Object o, Object[] elements, int index, int fence) { if (o == null) { for (int i = index; i < fence; i++) if (elements[i] == null) return i; } else { for (int i = index; i < fence; i++) if (o.equals(elements[i])) return i; } return -1;}private static int lastIndexOf(Object o, Object[] elements, int index) { if (o == null) { for (int i = index; i >= 0; i--) if (elements[i] == null) return i; } else { for (int i = index; i >= 0; i--) if (o.equals(elements[i])) return i; } return -1;}public boolean contains(Object o) { Object[] elements = getArray(); return indexOf(o, elements, 0, elements.length) >= 0;}public int indexOf(Object o) { Object[] elements = getArray(); return indexOf(o, elements, 0, elements.length);}public int indexOf(E e, int index) { Object[] elements = getArray(); return indexOf(e, elements, index, elements.length);}public int lastIndexOf(Object o) { Object[] elements = getArray(); return lastIndexOf(o, elements, elements.length - 1);}public int lastIndexOf(E e, int index) { Object[] elements = getArray(); return lastIndexOf(e, elements, index);}@SuppressWarnings("unchecked")private E get(Object[] a, int index) { return (E) a[index];}public E get(int index) { return get(getArray(), index);}</span>看下一些可变操作的方法。
set:
<span style="font-size:18px;">/** 写方法整体流程差不多都是:加锁-获取旧的数组-复制数组-写数组-设置新的-释放锁 */public E set(int index, E element) { final ReentrantLock lock = this.lock; lock.lock(); //基本上所有的写操作都会加锁 try { Object[] elements = getArray(); //获取旧的数组 E oldValue = get(elements, index); if (oldValue != element) { int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len); //底层native方法,最后内存复制一份数组出来 newElements[index] = element; setArray(newElements); } else { // Not quite a no-op; ensures volatile write semantics setArray(elements); //值相同时还是setArray了下,保证volatile语义,所有的写对读可见 } return oldValue; } finally { lock.unlock(); }}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); //数组长度+1 newElements[len] = e; setArray(newElements); return true; } finally { lock.unlock(); }}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); else { newElements = new Object[len + 1]; System.arraycopy(elements, 0, newElements, 0, index); //指定位置拆分数组复制 System.arraycopy(elements, index, newElements, index + 1, numMoved); } newElements[index] = element; setArray(newElements); } finally { lock.unlock(); }}</span>其他的写方法都差不多,整个流程就是写加锁-copy新数组-对新数组操作-解锁。
CopyOnWriteArraySet内部持有一个CopyOnWriteArrayList引用,所有操作都是基于对CopyOnWriteArrayList的操作。
CopyOnWriteArrayList没什么可说的,采用类似读写分析的机制,所有的写操作,都会复制一份数组出来操作,所以不太适合频繁写的场景,适合读多写少的场景。
0 0
- JUC源码分析24-队列-CopyOnWriteArrayList,CopyOnWriteArraySet
- 《Java源码分析》:CopyOnWriteArrayList/ CopyOnWriteArraySet
- 《Java源码分析》:CopyOnWriteArrayList/ CopyOnWriteArraySet
- Java多线程 -- JUC包源码分析2 -- Copy On Write/CopyOnWriteArrayList/CopyOnWriteArraySet
- Java多线程 -- JUC包源码分析2 -- Copy On Write/CopyOnWriteArrayList/CopyOnWriteArraySet
- JUC (三)—— CopyOnWriteArrayList、CopyOnWriteArraySet
- 【JDK】:CopyOnWriteArrayList、CopyOnWriteArraySet 源码解析
- CopyOnWriteArrayList与CopyOnWriteArraySet源码简析
- CopyOnWriteArrayList&CopyOnWriteArraySet
- juc--CopyOnWriteArraySet
- JUC源码分析17-队列-ArrayBlockingQueue
- JUC源码分析18-队列-LinkedBlockingQueue
- JUC源码分析19-队列-PriorityBlockingQueue
- JUC源码分析20-队列-DelayQueue
- JUC源码分析21-队列-LinkedBlockingDeque
- JUC源码分析22-队列-SynchronousQueue
- JUC源码分析23-队列-ConcurrentLinkedQueue
- JUC源码分析25-队列-LinkedTransferQueue
- addslashes() Versus mysql_real_escape_string()
- 一个很强大的LOG开关
- 做的webapp上线
- 树结构练习——判断给定森林中有多少棵树
- Nginx(2) 启动,停止,信号控制
- JUC源码分析24-队列-CopyOnWriteArrayList,CopyOnWriteArraySet
- 数人云CTO解读Docker 1.12和金融业容器化
- ORACLE日期时间函数大全
- axis2:用ant脚本生成webservice client 端的java/c代码
- 一般网站注册密码生成器
- IOS去除文件后缀名
- activiti当前流程高亮显示
- HDOJ-----1285拓扑排序
- JavaWeb 项目调试心得