java 線程安全的linkedlist_使ArrayList,LinkedList變成線程安全的

1.使用SynchronizedList

SynchronizedList是一個線程安全的包裝類。繼承于SynchronizedCollection,SynchronizedCollection實現了Collection接口,SynchronizedList包含一個List對象,對List的訪問修改方法進行了一些封裝,在封裝的方法中會對list使用同步鎖加鎖,然后再進行存取和修改操作。

使用方法如下

LinkedList linkedList = new LinkedList();

//調用Collections的synchronizedList方法,傳入一個linkedList,會返回一個SynchronizedList實例對象

List synchronizedList = Collections.synchronizedList(linkedList);

//調用Collections的synchronizedList方法,ArrayList,返回一個SynchronizedRandomAccessList實例對象

ArrayList arrayList = new ArrayList();

List synchronizedRandomAccessList = Collections.synchronizedList(linkedList);

(Collections.synchronizedList()方法會判斷傳入的對象是否實現了 RandomAccess接口,是的話,會返回一個SynchronizedRandomAccessList對象,SynchronizedRandomAccessList是SynchronizedList的子類,只是會多一個以線程安全的方式獲取子數組的方法)。

SynchronizedList類的部分代碼如下:

static class SynchronizedList

extends SynchronizedCollection

implements List {

final List list;//源list

final Object mutex;

SynchronizedCollection(Collection c) {

this.c = Objects.requireNonNull(c);

mutex = this;//mutex就是SynchronizedList實例自己,作為同步鎖使用

}

public E get(int index) {

synchronized (mutex) {

是父類中的成員變量,在父類中會將list賦值給mutex

return list.get(index);

}

}

public E set(int index, E element) {

synchronized (mutex) {return list.set(index, element);}

}

}

2.使用CopyOnWriteArrayList

CopyOnWriteArrayList跟ArrayList類似,都是實現了List接口,只不過它的父類是Object,而不是AbstractList。CopyOnWriteArrayList與ArrayList的不同在于,

1.內部持有一個ReentrantLock類型的lock成員變量,

final transient ReentrantLock lock = new ReentrantLock();

在對數組進行修改的方法中,都會先獲取lock,獲取成功才能進行修改,修改完釋放鎖,保證每次只允許一個線程對數組進行修改。

2.CopyOnWriteArrayList內部用于存儲元素的Object數組使用volatile

//CopyOnWriteArrayList

private transient volatile Object[] array;

//ArrayList

private transient Object[] elementData;//transient

可以看到區別主要在于CopyOnWriteArrayList的Object是使用volatile來修飾的,volatile可以使變量具備內存可見性,一個線程在工作內存中對變量進行修改后,會立即更新到物理內存,并且使得其他線程中的這個變量緩存失效,其他線程在讀取會去物理內存中讀取最新的值。(volatile修飾的是指向數組的引用變量,所以對數組添加元素,刪除元素不會改變引用,所以為了保證內存可見性,CopyOnWriteArrayList.add()方法在添加元素時,都是復制出一個新數組,進行修改操作后,再設置到就數組上)

注意事項:Object數組都使用transient修飾是因為transient修飾的屬性不會參與序列化,ArrayList通過實現writeObject()和readObject()方法來自定義了序列化方法(基于反序列化時節約空間考慮,如果用默認的序列方法,源elementData數組長度為100,實際只有10個元素,反序列化時也會分配長度為100的數組,造成內存浪費。)

public boolean add(E e) {

final ReentrantLock lock = this.lock;

//1. 使用Lock,保證寫線程在同一時刻只有一個

lock.lock();

try {

//2. 獲取舊數組引用

Object[] elements = getArray();

int len = elements.length;

//3. 創建新的數組,并將舊數組的數據復制到新數組中

Object[] newElements = Arrays.copyOf(elements, len + 1);

//4. 往新數組中添加新的數據

newElements[len] = e;

//5. 將舊數組引用指向新的數組

setArray(newElements);

return true;

} finally {

lock.unlock();

}

}

3.SynchronizedList和CopyOnWriteArrayList優缺點

SynchronizedList是通過對讀寫方法使用synchronized修飾來實現同步的,即便只是多個線程在讀數據,也不能進行,如果是讀比較多的場景下,會性能不高,所以適合讀寫均勻的情況。

而CopyOnWriteArrayList是讀寫分離的,只對寫操作加鎖,但是每次寫操作(添加和刪除元素等)時都會復制出一個新數組,完成修改后,然后將新數組設置到舊數組的引用上,所以在寫比較多的情況下,會有很大的性能開銷,所以適合讀比較多的應用場景。

原創文章,作者:9IM,如若轉載,請注明出處:https://www.9im.cn/500.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/540994.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/540994.shtml
英文地址,請注明出處:http://en.pswp.cn/news/540994.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

人工智能能夠構建一個自主驅動云嗎?

企業和組織可以從云計算中受益,但許多公司并不希望面對公共云的成本,性能和治理問題,并且認為構建自己的私有云的復雜性和運營開銷并沒有那么困難。 如今,一些云計算供應商正在使用人工智能(AI)來簡化私有云…

scala中def_def關鍵字以及Scala中的示例

scala中defScala def關鍵字 (Scala def keyword) The def keyword in Scala is used to declare functions and methods in Scala. Scala being ignorant on the data types does the same with the return type of a function. Declaring and defining a function in Scala do…

前端必備的 web 安全知識手記

前言 安全這種東西就是不發生則已,一發生則驚人。作為前端,平時對這方面的知識沒啥研究,最近了解了下,特此沉淀。文章內容包括以下幾個典型的 web 安全知識點:XSS、CSRF、點擊劫持、SQL 注入和上傳問題等(…

php腳本開頭注釋_PHP文件注釋標記及規范小結

PHP文件注釋標記及規范小結發布時間:2016-06-17 來源: 點擊:次PHP 注釋標記access使用范圍:class,function,var,define,module該標記用于指明關鍵字的存取權限:private、public或protecedauthor指明作者copyright使用范圍&#xf…

Salesforce宣布5.82億美元收購文件編輯公司Quip

北京時間8月2日消息,據路透社報道,云軟件開發商Salesforce.com周一宣布,已同意以大約5.82億美元收購文件編輯創業公司Quip。 Salesforce此前已經對Quip進行了投資。Quip開發的文字處理平臺供企業員工用于在移動設備、可穿戴設備以及臺式機上編…

Java中的main()方法是強制性的嗎?

The question is that "Is main() method is compulsory in Java?" 問題是“ main()方法在Java中是強制性的嗎?” Yes, we can write a java program without main() method but there is a condition if and only if java JDK version till JDK 5. 是的…

php date( w ),PHP Date()函數詳解

頁面的最上方加上:date_default_timezone_set(PRC); /*把時間調到北京時間,php5默認為格林威治標準時間*/date ()a: "am"或是"pm"A: "AM"或是"PM"d: 幾日,兩位數字,若不足則補零&#xff1b…

10.6-全棧Java筆記:常見流詳解(四)

上節我們講到「Java中常用流:數據流和對象流」,本節我們學習文件字符流和文件緩沖流~文件字符流前面介紹的文件字節流可以處理所有的文件,但是字節流不能很好的處理Unicode字符,經常會出現“亂碼”現象。所以,我們處理…

python 示例_帶有示例的Python File open()方法

python 示例文件open()方法 (File open() Method) open() method is an inbuilt method in Python, it is used to create, open or append a file. open()方法是Python中的內置方法,用于創建,打開或附加文件。 Syntax: 句法: file_object …

php屬于腳本,php是腳本語言嗎

PHP即“超文本預處理器”,是一種通用開源腳本語言。PHP是在服務器端執行的腳本語言,與C語言類似,是常用的網站編程語言。PHP獨特的語法混合了C、Java、Perl以及 PHP 自創的語法。利于學習,使用廣泛,主要適用于Web開發領…

NetMarketShare:本月桌面瀏覽器市場份額幾乎沒有變化

NetMarketShare之前關于臺式機瀏覽器市場份額的報告表示,Google Chrome市場份額正在快速上升,而Edge瀏覽器市場份額正在以蝸牛的速度前進。而該公司的最新統計數據顯示,幾乎所有瀏覽器的市場份額或多或少保持不變。 NetMarketShare的最新統計…

treeset java_Java TreeSet add()方法與示例

treeset javaTreeSet類的add()方法 (TreeSet Class add() method) add() method is available in java.util package. add()方法在java.util包中可用。 add() method is used to add the given object(ob) to this TreeSet when it does not already exist otherwise it ignore…

php fpm www.conf,PHP7中php.ini、php-fpm和www.conf 配置

PHP7中php.ini、php-fpm和www.conf 配置php.ini是php運行核心配置文件,下面是一些常用配置extension_dir""● 設置PHP的擴展庫路徑expose_php Off● 避免PHP信息暴露在http頭中display_errors Off● 避免暴露php調用mysql的錯誤信息log_errors On● 在關閉display…

服務器電流源泉ups電源的三大形式

還記得此前12306官網癱瘓,回家心切急于購票的我們只能感到無比心累。雙十一前夕,守在購物車邊準備瘋狂購物的剁手黨們,遇到一直呈現加載狀態的頁面,不得不感嘆想要做馬云背后的那個人也要大費周折。作為一個資深網民,不…

timer purge_Java Timer purge()方法與示例

timer purge計時器類purge()方法 (Timer Class purge() method) purge() method is available in java.util package. purge()方法在java.util包中可用。 purge() method is used to remove all canceled tasks from the task queue of this Timer. purge()方法用于從此Timer的…

大話Linux內核中鎖機制之原子操作、自旋鎖【轉】

轉自:http://blog.sina.com.cn/s/blog_6d7fa49b01014q7p.html 多人會問這樣的問題,Linux內核中提供了各式各樣的同步鎖機制到底有何作用?追根到底其實是由于操作系統中存在多進程對共享資源的并發訪問,從而引起了進程間的競態。這…

hashmap put方法_Java HashMap put()方法與示例

hashmap put方法HashMap類的put()方法 (HashMap Class put() method) put() method is available in java.util package. put()方法在java.util包中可用。 put() method is used to link the given value element with the given key element in this HashMap. put()方法用于在…

java中jdom,java – JDOM中的命名空間(默認)

我正在嘗試使用最新的JDOM包生成XML文檔.我遇到了根元素和命名空間的問題.我需要生成這個根元素:xmlns"http://www.energystar.gov/manageBldgs/req"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://www.…

java enummap_Java EnumMap get()方法與示例

java enummapEnumMap類的get()方法 (EnumMap Class get() method) get() method is available in java.util package. get()方法在java.util包中可用。 get() method is used to get the value mapped with the given key element (key_ele) otherwise it returns null when no…

java后臺json傳遞,后臺json傳遞

json除了可以用于前臺傳遞,還可用于后臺之間傳遞。它可以傳遞List,Map,Bean等類型的數據。例如:User u1new User();u1.setUsername("zy");u1.setPassword("123");User u2new User();u2.setUsername("msl");u2.setPassword…