Java并發(fā)J.U.C并發(fā)容器類list set queue
1. List
ArrayList
- 本質(zhì)就是一個(gè)數(shù)組
- 初識(shí)化大小默認(rèn)為 10
/** * Default initial capacity. */ private static final int DEFAULT_CAPACITY = 10;
- 每次擴(kuò)容后大小變?yōu)樵笮〉?.5倍
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); // 擴(kuò)容為1.5倍大小 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); }
- 使用
for(Object o : list)
迭代器進(jìn)行迭代循環(huán)的時(shí)候不應(yīng)該對(duì)列表list
進(jìn)行新增或者刪除操作,否則會(huì)報(bào)ConcurrentModificationException
異常,原因是因?yàn)榈^(guò)程中會(huì)檢查變量數(shù)量和期望的數(shù)量是否一致。
如以下操作就會(huì)報(bào)錯(cuò)
int i=0; for (Object o : list) { if(i==0) list.add("neco"); i++; }
拋出異常的代碼
final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }
LinkedList
- 本質(zhì)就是一個(gè)鏈表,沒有什么特殊的內(nèi)容
- 里邊的Node<E>是支持雙向鏈表的
private static class Node<E> { E item; Node<E> next; Node<E> prev; Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } }
CopyOnWriteArrayList
- 在寫的時(shí)候復(fù)制了一份出來(lái),然后重新寫入數(shù)據(jù)
/** * Appends the specified element to the end of this list. * * @param e element to be appended to this list * @return {@code true} (as specified by {@link Collection#add}) */ 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(); } }
- 確保了讀寫可以同步進(jìn)行,但是可能會(huì)有臟讀的情況
- 在多讀少寫的情況下可以使用
CopyOnWriteArrayList容器即寫時(shí)復(fù)制的容器。
和ArrayList比較,優(yōu)點(diǎn)是并發(fā)安全,缺點(diǎn)有兩個(gè):
1、多了內(nèi)存占用:寫數(shù)據(jù)是copy一份完整的數(shù)據(jù),單獨(dú)進(jìn)行操作。占用雙份內(nèi)存。
2、數(shù)據(jù)一致性:數(shù)據(jù)寫完之后,其他線程不一定是馬上讀取到最新內(nèi)容。
CopyOnWriteArrayList
2. Set 集合
和List比較:不會(huì)重復(fù)
實(shí)現(xiàn) | 原理 | 特點(diǎn) |
---|---|---|
HashSet | 基于HashMap實(shí)現(xiàn) | 非線程安全 |
CopyOnWriteArraySet | 基于CopyOnWriteArrayList | 線程安全 |
TreeSet | 基于TreeMap | 線程安全,有序,查詢快 |
HashSet
內(nèi)部的實(shí)現(xiàn)本質(zhì)就是一個(gè)Map(因?yàn)閗ey值不重復(fù)),但是只是使用了Key,對(duì)于value無(wú)所謂
/** * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has * default initial capacity (16) and load factor (0.75). */ public HashSet() { map = new HashMap<>(); } /** * Adds the specified element to this set if it is not already present. * More formally, adds the specified element <tt>e</tt> to this set if * this set contains no element <tt>e2</tt> such that * <tt>(e==null ? e2==null : e.equals(e2))</tt>. * If this set already contains the element, the call leaves the set * unchanged and returns <tt>false</tt>. * * @param e element to be added to this set * @return <tt>true</tt> if this set did not already contain the specified * element */ public boolean add(E e) { return map.put(e, PRESENT)==null; } // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object();
CopyOnWriteArraySet
內(nèi)部的本質(zhì)是一個(gè) CopyOnWriteArrayList,通過(guò)判斷是否存在來(lái)確定是否放入數(shù)據(jù)
/** * Creates an empty set. */ public CopyOnWriteArraySet() { al = new CopyOnWriteArrayList<E>(); } /** * Adds the specified element to this set if it is not already present. * More formally, adds the specified element {@code e} to this set if * the set contains no element {@code e2} such that * <tt>(e==null ? e2==null : e.equals(e2))</tt>. * If this set already contains the element, the call leaves the set * unchanged and returns {@code false}. * * @param e element to be added to this set * @return {@code true} if this set did not already contain the specified * element */ public boolean add(E e) { return al.addIfAbsent(e); } /** * Appends the element, if not present. * * @param e element to be added to this list, if absent * @return {@code true} if the element was added */ public boolean addIfAbsent(E e) { Object[] snapshot = getArray(); return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false : addIfAbsent(e, snapshot); } /** * A version of addIfAbsent using the strong hint that given * recent snapshot does not contain e. */ private boolean addIfAbsent(E e, Object[] snapshot) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] current = getArray(); int len = current.length; if (snapshot != current) { // Optimize for lost race to another addXXX operation int common = Math.min(snapshot.length, len); for (int i = 0; i < common; i++) if (current[i] != snapshot[i] && eq(e, current[i])) return false; if (indexOf(e, current, common, len) >= 0) return false; } Object[] newElements = Arrays.copyOf(current, len + 1); newElements[len] = e; setArray(newElements); return true; } finally { lock.unlock(); } }
TreeSet
本質(zhì)是一個(gè)TreeMap,但是也只用到了Key值,Value值沒有什么意義。
/** * Constructs a new, empty tree set, sorted according to the * natural ordering of its elements. All elements inserted into * the set must implement the {@link Comparable} interface. * Furthermore, all such elements must be <i>mutually * comparable</i>: {@code e1.compareTo(e2)} must not throw a * {@code ClassCastException} for any elements {@code e1} and * {@code e2} in the set. If the user attempts to add an element * to the set that violates this constraint (for example, the user * attempts to add a string element to a set whose elements are * integers), the {@code add} call will throw a * {@code ClassCastException}. */ public TreeSet() { this(new TreeMap<E,Object>()); } /** * Adds the specified element to this set if it is not already present. * More formally, adds the specified element {@code e} to this set if * the set contains no element {@code e2} such that * <tt>(e==null ? e2==null : e.equals(e2))</tt>. * If this set already contains the element, the call leaves the set * unchanged and returns {@code false}. * * @param e element to be added to this set * @return {@code true} if this set did not already contain the specified * element * @throws ClassCastException if the specified object cannot be compared * with the elements currently in this set * @throws NullPointerException if the specified element is null * and this set uses natural ordering, or its comparator * does not permit null elements */ public boolean add(E e) { return m.put(e, PRESENT)==null; } // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object();
SET接口沒有所謂的有序還是無(wú)序。 TreeSet是有序的,此有序是說(shuō)讀取數(shù)據(jù)的順序和插入數(shù)據(jù)的順序一樣。
HashSet無(wú)序? 此無(wú)序說(shuō)的是讀取數(shù)據(jù)的順序不一定和插入數(shù)據(jù)的順序一樣。
3. Queue
Queue API
Queue -隊(duì)列數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn)。分為阻塞隊(duì)列和非阻塞隊(duì)列。下列的藍(lán)色區(qū)塊,為阻塞隊(duì)列特有的方法。
Queue API
阻塞是通過(guò)condition來(lái)實(shí)現(xiàn)的,可參考 Java并發(fā) - Lock接口
- ArrayBlockingQueue 阻塞
- LinkedBlockingQueue 阻塞
- ArrayQueue 非阻塞
- LinkedQueue 非阻塞
以上就是Java并發(fā) - J.U.C并發(fā)容器類 list、set、queue的詳細(xì)內(nèi)容,更多關(guān)于Java J.U.C并發(fā)容器類的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot項(xiàng)目打成War包部署的方法步驟
這篇文章主要介紹了springboot項(xiàng)目如何打war包流程的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12如何配置cursor進(jìn)行Java springboot項(xiàng)目開發(fā)
本文介紹了如何在Cursor IDE中配置Java和Spring Boot項(xiàng)目開發(fā)環(huán)境,首先,設(shè)置了系統(tǒng)用戶級(jí)別的JDK配置,以便在多個(gè)項(xiàng)目之間切換時(shí)不需要重新配置,然后,配置了Gradle環(huán)境變量,并安裝了必要的Java開發(fā)插件,感興趣的朋友跟隨小編一起看看2025-02-02Java中JavaBean對(duì)象和Map的互相轉(zhuǎn)換方法實(shí)例
為什么需要將javaBean和map進(jìn)行轉(zhuǎn)換,在很多應(yīng)用場(chǎng)景中,需要將key=value形式的數(shù)據(jù)與javaBean對(duì)象相互轉(zhuǎn)換,下面這篇文章主要給大家介紹了關(guān)于Java中JavaBean對(duì)象和Map的互相轉(zhuǎn)換的相關(guān)資料,需要的朋友可以參考下2022-11-11SpringBoot(JAVA)整合微信公眾號(hào)消息推送完整步驟(文本、圖片/視頻推送)
微信公眾號(hào)消息推送包括文本推送和圖文/視頻推送兩類,文本推送通過(guò)模板消息或自定義消息實(shí)現(xiàn),而圖文/視頻推送需先上傳素材至臨時(shí)/永久素材庫(kù),再上傳圖文消息,最后進(jìn)行消息推送,文中將實(shí)現(xiàn)的方法介紹的非常詳細(xì),需要的朋友可以參考下2024-09-09Java過(guò)濾器doFilter里chain.doFilter()函數(shù)的理解
這篇文章主要介紹了Java過(guò)濾器doFilter里chain.doFilter()函數(shù)的理解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11Java基于Swing和netty實(shí)現(xiàn)仿QQ界面聊天小項(xiàng)目
這篇文章主要為大家詳細(xì)介紹了Java如何利用Swing和netty實(shí)現(xiàn)仿QQ界面聊天小項(xiàng)目,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-09-09springboot基于keytool實(shí)現(xiàn)https的雙向認(rèn)證示例教程
這篇文章主要介紹了springboot基于keytool實(shí)現(xiàn)https的雙向認(rèn)證,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06淺談spring中isolation和propagation的用法
這篇文章主要介紹了淺談spring中isolation 和propagation的用法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07