Java中ArrayList同步的2種方法分享
前言:
arrayList
的實(shí)現(xiàn)是默認(rèn)不同步的。這意味著如果一個(gè)線程在結(jié)構(gòu)上修改它并且多個(gè)線程同時(shí)訪問(wèn)它,它必須在外部同步。結(jié)構(gòu)修改意味著從列表中添加或刪除元素或顯式調(diào)整后備數(shù)組的大小。改變現(xiàn)有元素的值不是結(jié)構(gòu)修改。
有兩種方法可以創(chuàng)建同步Arraylist:
- 1. Collections.synchronizedList() 方法。
- 2. 使用 CopyOnWriteArrayList。
方法1:使用 Collections.synchronizedList() 方法
要進(jìn)行串行訪問(wèn),必須通過(guò)返回列表完成對(duì)后備列表的所有訪問(wèn)。
在迭代返回的列表時(shí),用戶必須手動(dòng)同步它。因?yàn)樵趫?zhí)行add()等方法的時(shí)候是加了synchronized
關(guān)鍵字的,但是iterator()卻沒(méi)有加。所以在使用的時(shí)候需要加上synchronized
。
// Java program to demonstrate working of // Collections.synchronizedList import java.util.*; ? class GFG { ?? ?public static void main (String[] args) ?? ?{ ?? ??? ?List<String> list = ?? ??? ?Collections.synchronizedList(new ArrayList<String>()); ? ?? ??? ?list.add("practice"); ?? ??? ?list.add("code"); ?? ??? ?list.add("quiz"); ? ?? ??? ?synchronized(list) ?? ??? ?{ ?? ??? ??? ?// must be in synchronized block ?? ??? ??? ?Iterator it = list.iterator(); ? ?? ??? ??? ?while (it.hasNext()) ?? ??? ??? ??? ?System.out.println(it.next()); ?? ??? ?} ?? ?} }
方法 2:使用 CopyOnWriteArrayList
ArrayList
的線程安全變體,其中所有可變操作(例如添加、設(shè)置、刪除...)都是通過(guò)創(chuàng)建底層數(shù)組的單獨(dú)副本來(lái)實(shí)現(xiàn)的。它通過(guò)創(chuàng)建 List 的單獨(dú)副本來(lái)實(shí)現(xiàn)線程安全,這與 vector 或其他集合用于提供線程安全的方式不同。
- 當(dāng)我們不能或不想同步遍歷,但需要防止并發(fā)線程之間的干擾時(shí),它很有用。
- 這是昂貴的,因?yàn)槊看螌?xiě)入操作都涉及單獨(dú)的數(shù)組副本(例如添加,設(shè)置,刪除......)
- 當(dāng)你有List并且需要遍歷它的元素并且不經(jīng)常修改它時(shí),它是非常有效的。
即使在創(chuàng)建迭代器后修改了 copyOnWriteArrayList
,迭代器也不會(huì)拋出ConcurrentModificationException
,因?yàn)榈髡诘?ArrayList 的單獨(dú)副本,而寫(xiě)操作正在 ArrayList 的另一個(gè)副本上發(fā)生。
// Java program to illustrate the thread-safe ArrayList. import java.io.*; import java.util.Iterator; import java.util.concurrent.CopyOnWriteArrayList; ? class GFG { ?? ?public static void main (String[] args) ?? ?{ ?? ??? ?// creating a thread-safe Arraylist. ?? ??? ?CopyOnWriteArrayList<String> threadSafeList ?? ??? ??? ?= new CopyOnWriteArrayList<String>(); ? ?? ??? ?// Adding elements to synchronized ArrayList ?? ??? ?threadSafeList.add("geek"); ?? ??? ?threadSafeList.add("code"); ?? ??? ?threadSafeList.add("practice"); ? ?? ??? ?System.out.println("Elements of synchronized ArrayList :"); ? ?? ??? ?// Iterating on the synchronized ArrayList using iterator. ?? ??? ?Iterator<String> it = threadSafeList.iterator(); ? ?? ??? ?while (it.hasNext()) ?? ??? ??? ?System.out.println(it.next()); ?? ?} }
如果我們嘗試通過(guò)迭代器自己的方法修改 CopyOnWriteArrayList 會(huì)發(fā)生什么?
如果您嘗試通過(guò)迭代器自己的方法(例如 add()、set()、remove())修改CopyOnWriteArrayList
,它會(huì)拋出 UnsupportedOperationException 。
// Java program to illustrate the thread-safe ArrayList import java.io.*; import java.util.Iterator; import java.util.concurrent.CopyOnWriteArrayList; ? class GFG { ?? ?public static void main (String[] args) ?? ?{ ?? ??? ?// creating a thread-safe Arraylist. ?? ??? ?CopyOnWriteArrayList<String> threadSafeList = ?? ??? ??? ?new CopyOnWriteArrayList<String>(); ? ?? ??? ?// Adding elements to synchronized ArrayList ?? ??? ?threadSafeList.add("geek"); ?? ??? ?threadSafeList.add("code"); ?? ??? ?threadSafeList.add("practice"); ? ?? ??? ?System.out.println("Elements of synchronized ArrayList :"); ? ?? ??? ?// Iterating on the synchronized ArrayList using iterator. ?? ??? ?Iterator<String> it = threadSafeList.iterator(); ? ?? ??? ?while (it.hasNext()) ?? ??? ?{ ?? ??? ??? ?String str = it.next(); ?? ??? ??? ?it.remove(); ?? ??? ?} ?? ?} }
CopyOnWriteArrayList 的其他構(gòu)造函數(shù):
- 1. CopyOnWriteArrayList(Collection<? extends E> c):創(chuàng)建一個(gè)包含指定集合元素的列表,按照集合迭代器返回的順序。
- 2. CopyOnWriteArrayList(E[] toCopyIn):創(chuàng)建一個(gè)包含給定數(shù)組副本的列表。
向量同步時(shí)為什么要使用arrayList?
- 性能:
Vector
是同步和線程安全的,因此,它比ArrayList
稍慢。 - 功能: Vector 在每個(gè)單獨(dú)的操作級(jí)別進(jìn)行同步。通常,程序員喜歡同步整個(gè)操作序列。同步單個(gè)操作既不安全又慢。
- Vectors obsolete:向量被認(rèn)為是過(guò)時(shí)的,并且在 java 中被非正式地棄用。此外,vector 對(duì)幾乎從未完成的每個(gè)單獨(dú)操作進(jìn)行同步。大多數(shù)java程序員更喜歡使用
ArrayList
,因?yàn)槿绻麄冃枰M(jìn)行同步,他們可能無(wú)論如何都會(huì)顯式地同步arrayList。
以下是 Java 中 ArrayList
和 CopyOnWriteArrayList
類(lèi)之間的顯著差異。
數(shù)組列表 | 復(fù)制寫(xiě)入數(shù)組列表 | |
---|---|---|
同步 | ArrayList 不同步。 | CopyOnWriteArrayList 是同步的。 |
線程安全 | ArrayList 不是線程安全的。 | CopyOnWriteArrayList 是線程安全的。 |
迭代器類(lèi)型 | ArrayList 迭代器是快速失敗的,如果在迭代過(guò)程中發(fā)生并發(fā)修改,則 ArrayList 會(huì)拋出 ConcurrentModificationException。 | CopyOnWriteArrayList 是故障安全的,它在迭代過(guò)程中永遠(yuǎn)不會(huì)拋出 ConcurrentModificationException。其背后的原因是 CopyOnWriteArrayList 每次修改時(shí)都會(huì)創(chuàng)建一個(gè)新的數(shù)組列表。 |
刪除操作 | ArrayList 迭代器支持在迭代過(guò)程中移除元素。 | 如果在迭代期間嘗試刪除元素,則 CopyOnWriteArrayList.remove() 方法會(huì)引發(fā)異常。 |
表現(xiàn) | ArrayList 更快。 | CopyOnWriteArrayList 比 ArrayList 慢。 |
從 Java 版本開(kāi)始 | 1.2 | 1.5 |
到此這篇關(guān)于Java中ArrayList同步的2種方法分享的文章就介紹到這了,更多相關(guān)Java中ArrayList同步內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Security實(shí)現(xiàn)微信公眾號(hào)網(wǎng)頁(yè)授權(quán)功能
這篇文章主要介紹了Spring Security中實(shí)現(xiàn)微信網(wǎng)頁(yè)授權(quán),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-08-08spring-boot實(shí)現(xiàn)增加自定義filter(新)
本篇文章主要介紹了spring-boot實(shí)現(xiàn)增加自定義filter(新),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05怎樣提高mybatis-plus中saveBatch方法的效率
這篇文章主要介紹了怎樣提高mybatis-plus中saveBatch方法的效率問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07Java?HashMap中除了死循環(huán)之外的那些問(wèn)題
這篇文章主要介紹了Java?HashMap中除了死循環(huán)之外的那些問(wèn)題,這些問(wèn)題大致可以分為兩類(lèi),程序問(wèn)題和業(yè)務(wù)問(wèn)題,下面文章我們一個(gè)一個(gè)來(lái)看,需要的小伙伴可以參考一下2022-05-05