Categories
程式開發

源碼分析Vector和ArrayList



{“ type”:“ doc”,“ content”:[{“type”:”paragraph”,”attrs”:{“indent”:0,”number”:0,”align”:null,”origin”:null}},{“type”:”heading”,”attrs”:{“align”:null,”level”:2},”content”:[{“type”:”text”,”text”:”源码分析 Vector 和 ArrayList “}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null}},{“ type”:“ paragraph” ,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null},“ content”:[{“type”:”text”,”text”:”每次我们会被问到这个问题,我们都知道 Vector 是线程安全的,而 ArrayList是线程不安全的。今天想引申出几个问题。”}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null}},{“ type”:“ numberedlist” ,“ attrs”:{“ start”:1,“ normalizeStart”:1},“ content”:[{“type”:”listitem”,”content”:[{“type”:”paragraph”,”attrs”:{“indent”:0,”number”:1,”align”:null,”origin”:null},”content”:[{“type”:”text”,”text”:”Vector 和 ArrayList 还有什么不同”}]}]},{“ type”:“ listitem”,“ content”:[{“type”:”paragraph”,”attrs”:{“indent”:0,”number”:2,”align”:null,”origin”:null},”content”:[{“type”:”text”,”text”:”Vector 容器是如何实现线程安全的”}]}]},{“ type”:“ listitem”,“ content”:[{“type”:”paragraph”,”attrs”:{“indent”:0,”number”:3,”align”:null,”origin”:null},”content”:[{“type”:”text”,”text”:”如果在多线程环境下,有没有别的 List 容器推荐,分别使用在什么场景?”}]}]}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null}},{“ type”:“ paragraph” ,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null}},{“ type”:“ heading”,“ attrs”:{“ align”: null,“ level”:2},“ content”:[{“type”:”text”,”text”:”首先回答第一个问题 Vector和ArrayList还有什么不同?”}]},{“ type”:“ image”,“ attrs”:{“ src”:“ https://static001.geekbang.org/infoq/49/49a8681da0690e9737e487b8c9cf9a0f.png”,“ alt”:null,“ title”: ““,“樣式”:[{“key”:”width”,”value”:”100%”},{“key”:”bordertype”,”value”:”none”}],“ href”:“”,“ fromPaste”:false,“ pastePass”:false}},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align “:null,” origin“:null}},{” type“:” paragraph“,” attrs“:{” indent“:0,” number“:0,” align“:null,” origin“:null} },{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null},“ content”:[{“type”:”text”,”text”:”上图我们可以看到,Vetor和ArrayList都继承自AbstractList,所以大体上对外提供的接口大致相同,只是内部实现不同,底层都是基于数组加上扩容机制实现,除线程安全外Vetor和ArrayList最大的不同就是扩容方式不同,我们先给出结论,Vector在扩容时是提高一倍容量,而ArrayList是50%。下面我们可以具体分析一下扩容的源码。”}]},{“ type”:“標題”,“ attrs”:{“ align”:null,“ level”:3},“ content”:[{“type”:”text”,”text”:”Vector”}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null},“ content”:[{“type”:”text”,”text”:”初始化方法”}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null}},{“ type”:“ codeblock” ,“ attrs”:{“ lang”:“ java”},“ content”:[{“type”:”text”,”text”:”/*n @param initialCapacity 内部数组的初始容量,默认为0n @param capacityIncrement 每次扩容的容量,如果不设置则成倍扩容n /npublic Vector(int initialCapacity, int capacityIncrement);nn/*n @param initialCapacity 初始容量n /npublic Vector(int initialCapacity);nn/n 初始化一个 初始容量为10,每次扩容一倍的Vertor容器n */npublic Vertor();n”}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null}},{“ type”:“ paragraph” ,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null},“ content”:[{“type”:”text”,”text”:”我们从add(Object o)入手”}]},{“ type”:“ codeblock”,“ attrs”:{“ lang”:“ java”},“ content”:[{“type”:”text”,”text”:”public synchronized boolean add(E e) {n modCount++;n add(e, elementData, elementCount);n return true;n}”}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null},“ content”:[{“type”:”text”,”text”:”可以看到add方法是加了synchronized关键字,这就说明Vector的add()方法在同一时刻只有一个线程能获取到锁,一目了然,Vector是使用 synchronized 同步机制实现到线程安全,它的每一个对外提供的 api 上都加有 synchronized 关键字。”}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null}},{“ type”:“ paragraph” ,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null},“ content”:[{“type”:”text”,”text”:”下面我们看一下 add(e, elementData, elementCount); 这个方法”}]},{“ type”:“ codeblock”,“ attrs”:{“ lang”:“ java”},“ content”:[{“type”:”text”,”text”:”private void add(E e, Object[] elementData,int s){ n如果(s == elementData.length) n elementData = grow(); n elementData[s] = e; n elementCount = s + 1; n}“}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null},“ content”:[{“type”:”text”,”text”:”其中 e代表添加的元素,elementData代表内部的数组,s当前的容量。注意elementData数组的长度和s不是相同的,比如 Vector初始化的时候, elementData的初始化长度是10,而s=0。上面我们可以看到,如果当前容量s = 内部数组的长度以后,就需要调用 grow() 方法获取一个新的 内部数组,扩容的逻辑就在 grow() 方法里面。”}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null}},{“ type”:“ paragraph” ,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null},“ content”:[{“type”:”text”,”text”:”下面我们看一下 grow() 方法:”}]},{“ type”:“ codeblock”,“ attrs”:{“ lang”:“ java”},“ content”:[{“type”:”text”,”text”:”private Object[] grow(){ n // elementCount代表內部多重的長度,初始化情況下是10。 n return grow(elementCount + 1); n} n n // minCapacity代表最小生成一個容量為minCapacity的預算 n私有對象[] grow(int minCapacity){ n // newCapacity(minCapacity)方法會生成一個新的數組 n return elementData = Arrays.copyOf(elementData,newCapacity(minCapacity)); n}“}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null}},{“ type”:“ paragraph” ,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null},“ content”:[{“type”:”text”,”text”:”来了来了,核心扩容逻辑来了 newCapacoty(int minCapacity)”}]},{“ type”:“ codeblock”,“ attrs”:{“ lang”:“ java”},“ content”:[{“type”:”text”,”text”:”private int newCapacity(int minCapacity) {n //获取当前数组的容量n int oldCapacity = elementData.length;n //获取扩容以后新数组的容量n //注意 capacityIncrement 是初始化 Vector 的时候可以自己设置的,表明每次扩容的大小n //如果没有设置capacityIncrement,我们可以看到 newCapacity = oldCapacity + oldCapacityn //也就是默认两倍扩容n int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);n //这里是一个极端的情况,我们都知道int类型都是有范围的,如果超过 2^31-1,就会变成负数,这个时候就说明,newCapacity 已经扩容到最大了,超纲了n if (newCapacity – minCapacity <= 0) {n //数组已满n if (minCapacity < 0) // overflown throw new OutOfMemoryError();n return minCapacity;n }n //这个地方就是保证数据扩容不超过int范围,如果超过了就不扩容了n //内部数据的容量如果超过了就会OOMn return (newCapacity - MAXARRAYSIZE <= 0)n ? newCapacityn : hugeCapacity(minCapacity);n}nnnprivate static int hugeCapacity(int minCapacity) {n if (minCapacity MAXARRAYSIZE) ?n Integer.MAXVALUE :n MAXARRAY_SIZE;n}n"}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null}},{“ type”:“ heading” ,“ attrs”:{“ align”:null,“ level”:3},“ content”:[{"type":"text","text":"ArrayList"}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null},“ content”:[{"type":"text","text":"构造方法"}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null}},{“ type”:“ codeblock” ,“ attrs”:{“ lang”:“ java”},“ content”:[{“type”:“text”,“text”:“/*[email protected]初始容量,設為為10n*/npublicArrayList(intinitialCapacity)nnpublicArrayList();nnpublicArrayList(Collection[{"type":"text""text":"/*[email protected]初始容量,默认为10n*/npublicArrayList(intinitialCapacity)nnpublicArrayList();nnpublicArrayList(Collection[{“type”:“text”,“text”:“/*[email protected]初始容量,設為為10n*/npublicArrayList(intinitialCapacity)nnpublicArrayList();nnpublicArrayList(Collection[{"type":"text""text":"/*[email protected]初始容量,默认为10n*/npublicArrayList(intinitialCapacity)nnpublicArrayList();nnpublicArrayList(Collection C);”}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null}},{“ type”:“ paragraph” ,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null},“ content”:[{“type”:”text”,”text”:”我们也从 add(Object o) 入手”}]},{“ type”:“ codeblock”,“ attrs”:{“ lang”:“ java”},“ content”:[{“type”:“text”,“text”:“publicbooleanadd(Ee){nmodCount++;nadd(e,elementData,size);n返回true;n}nnprivatevoidadd(Ee,對象[{“type”:”text””text”:”publicbooleanadd(Ee){nmodCount++;nadd(eelementDatasize);nreturntrue;n}nnprivatevoidadd(EeObject[{“type”:“text”,“text”:“publicbooleanadd(Ee){nmodCount++;nadd(e,elementData,size);n返回true;n}nnprivatevoidadd(Ee,對象[{“type”:”text””text”:”publicbooleanadd(Ee){nmodCount++;nadd(eelementDatasize);nreturntrue;n}nnprivatevoidadd(EeObject[] elementData,int s){ n如果(s == elementData.length) n elementData = grow(); n elementData[s] = e; n size = s + 1; n} n n私有對象[] grow(){ n返回grow(size + 1); n} n n私有對象[] grow(int minCapacity){ n返回elementData = Arrays.copyOf(elementData,newCapacity(minCapacity)); n}“}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null},“ content”:[{“type”:”text”,”text”:”我们可以看到,上面的方法,除了 add(E e) 方法没有 synchronized 关键字,基本都相同。”}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null}},{“ type”:“ paragraph” ,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null},“ content”:[{“type”:”text”,”text”:”下面我们看一下 newCapacity(int minCapacity) 这个方法”}]},{“ type”:“ codeblock”,“ attrs”:{“ lang”:“ java”},“ content”:[{“type”:”text”,”text”:” private int newCapacity(int minCapacity) {n //当前数组的容量n int oldCapacity = elementData.length;n //新数组的容量n int newCapacity = oldCapacity + (oldCapacity >> 1);n if (newCapacity – minCapacity <= 0) {n //newCapacity 超过2^31-1如何处理n if (elementData == DEFAULTCAPACITYEMPTYELEMENTDATA)n return Math.max(DEFAULTCAPACITY, minCapacity);n if (minCapacity < 0) // overflown throw new OutOfMemoryError();n return minCapacity;n }n return (newCapacity - MAXARRAYSIZE <= 0)n ? newCapacityn : hugeCapacity(minCapacity);n }nn private static int hugeCapacity(int minCapacity) {n if (minCapacity MAXARRAYSIZE)n ? Integer.MAXVALUEn : MAXARRAYSIZE;n }"}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null}},{“ type”:“ heading” ,“ attrs”:{“ align”:null,“ level”:2},“ content”:[{"type":"text","text":"ArrayList 线程安全处理"}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null},“ content”:[{"type":"text","text":"3.1 Collections.synchronizedList(new ArrayList); "}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null},“ content”:[{"type":"text","text":"3.2 CopyOnWriteArrayList() 容器,基于 ReadWriteLock 锁实现"}]},{“ type”:“ paragraph”,“ attrs”:{“ indent”:0,“ number”:0,“ align”:null,“ origin”:null}}]}