java集合框架線程同步代碼詳解
List接口的大小可變數(shù)組的實(shí)現(xiàn)。實(shí)現(xiàn)了所有可選列表操作,并允許包括null在內(nèi)的所有元素。除了實(shí)現(xiàn)List接口外,此類還提供一些方法來(lái)操作內(nèi)部用來(lái)存儲(chǔ)列表的數(shù)組的大小。(此類大致上等同于Vector類,除了此類是不同步的。)size、isEmpty、get、set、iterator和listIterator操作都以固定時(shí)間運(yùn)行。add操作以分?jǐn)偟墓潭〞r(shí)間運(yùn)行,也就是說(shuō),添加n個(gè)元素需要O(n)時(shí)間。其他所有操作都以線性時(shí)間運(yùn)行(大體上講)。與用于LinkedList實(shí)現(xiàn)的常數(shù)因子相比,此實(shí)現(xiàn)的常數(shù)因子較低。每個(gè)ArrayList實(shí)例都有一個(gè)容量。該容量是指用來(lái)存儲(chǔ)列表元素的數(shù)組的大小。它總是至少等于列表的大小。隨著向ArrayList中不斷添加元素,其容量也自動(dòng)增長(zhǎng)。并未指定增長(zhǎng)策略的細(xì)節(jié),因?yàn)檫@不只是添加元素會(huì)帶來(lái)分?jǐn)偣潭〞r(shí)間開(kāi)銷那樣簡(jiǎn)單。在添加大量元素前,應(yīng)用程序可以使用ensureCapacity操作來(lái)增加ArrayList實(shí)例的容量。這可以減少遞增式再分配的數(shù)量。
注意,此實(shí)現(xiàn)不是同步的。
如果多個(gè)線程同時(shí)訪問(wèn)一個(gè)ArrayList實(shí)例,而其中至少一個(gè)線程從結(jié)構(gòu)上修改了列表,那么它必須保持外部同步。(結(jié)構(gòu)上的修改是指任何添加或刪除一個(gè)或多個(gè)元素的操作,或者顯式調(diào)整底層數(shù)組的大?。粌H僅設(shè)置元素的值不是結(jié)構(gòu)上的修改。)這一般通過(guò)對(duì)自然封裝該列表的對(duì)象進(jìn)行同步操作來(lái)完成。如果不存在這樣的對(duì)象,則應(yīng)該使用Collections.synchronizedList方法將該列表“包裝”起來(lái)。這最好在創(chuàng)建時(shí)完成,以防止意外對(duì)列表進(jìn)行不同步的訪問(wèn):
Listlist=Collections.synchronizedList(newArrayList(...));
此類的iterator和listIterator方法返回的迭代器是快速失敗的:在創(chuàng)建迭代器之后,除非通過(guò)迭代器自身的remove或add方法從結(jié)構(gòu)上對(duì)列表進(jìn)行修改,否則在任何時(shí)間以任何方式對(duì)列表進(jìn)行修改,迭代器都會(huì)拋出ConcurrentModificationException。因此,面對(duì)并發(fā)的修改,迭代器很快就會(huì)完全失敗,而不是冒著在將來(lái)某個(gè)不確定時(shí)間發(fā)生任意不確定行為的風(fēng)險(xiǎn)。
注意,迭代器的快速失敗行為無(wú)法得到保證,因?yàn)橐话銇?lái)說(shuō),不可能對(duì)是否出現(xiàn)不同步并發(fā)修改做出任何硬性保證??焖偈〉鲿?huì)盡最大努力拋出ConcurrentModificationException。因此,為提高這類迭代器的正確性而編寫一個(gè)依賴于此異常的程序是錯(cuò)誤的做法:迭代器的快速失敗行為應(yīng)該僅用于檢測(cè)bug。
如上所示,現(xiàn)在建立一個(gè)list集合,一個(gè)線程對(duì)集合進(jìn)行寫入操作,一個(gè)線程進(jìn)行刪除操作
import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Random; public class MyArrayList { /** * 創(chuàng)建一個(gè)列表,一個(gè)線程進(jìn)行寫入,一個(gè)線程讀取 iterator 和 listIterator 方法返回的迭代器是快速失敗的 */ public void readWrite() { List<Integer> nums = new ArrayList<Integer>(); List<Integer> synNums = Collections.synchronizedList(nums); //啟動(dòng)寫入線程 new WriteListThread(synNums).start(); //啟動(dòng)刪除線程 new DeleteListThread(synNums).start(); } public static void main(String[] args) { new MyArrayList().readWrite(); } } class WriteListThread extends Thread { private List<Integer> nums; public WriteListThread(List<Integer> nums) { super(“WriteListThread”); this.nums = nums; } // 不停寫入元素1 public void run() { while (true) { nums.add(new Random().nextint(1000)); System.out.println(Thread.currentThread().getName()); } } } class DeleteListThread extends Thread { private List<Integer> nums; public DeleteListThread(List<Integer> nums) { super(“DeleteListThread”); this.nums = nums; } // 刪除第一個(gè)元素 public void run() { while (true) { try{ System.out.println(Thread.currentThread().getName()+”:”+nums.remove(0)); } catch(Exception e){ continue ; } } } }
通過(guò)List<Integer>synNums=Collections.synchronizedList(nums);就能對(duì)原子操作進(jìn)行同步了,但是官方api示例為什么要自己手動(dòng)添加同步呢?
List list = Collections.synchronizedList(new ArrayList()); synchronized(list) { Iterator i = list.iterator(); // Must be in synchronized block while (i.hasNext()) foo(i.next()); }
查看Collections.synchronizedList的源代碼
SynchronizedCollection(Collection<E> c) { if (c==null) throw new NullPointerException(); this.c = c; mutex = this; }
import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Random; public class MyArrayList { /** * 創(chuàng)建一個(gè)列表,一個(gè)線程進(jìn)行寫入,一個(gè)線程讀取 iterator 和 listIterator 方法返回的迭代器是快速失敗的 */ public void readWrite() { List<Integer> nums = new ArrayList<Integer>(); List<Integer> synNums = Collections.synchronizedList(nums); //啟動(dòng)寫入線程 new WriteListThread(synNums).start(); //啟動(dòng)刪除線程 new DeleteListThread(synNums).start(); } public static void main(String[] args) { new MyArrayList().readWrite(); } } class WriteListThread extends Thread { private List<Integer> nums; public WriteListThread(List<Integer> nums) { super("WriteListThread"); this.nums = nums; } // 不停寫入元素1 public void run() { while (true) { nums.add(new Random().nextint(1000)); System.out.println(Thread.currentThread().getName()); } } } class DeleteListThread extends Thread { private List<Integer> nums; public DeleteListThread(List<Integer> nums) { super("DeleteListThread"); this.nums = nums; } // 刪除第一個(gè)元素 public void run() { while (true) { try{ System.out.println(Thread.currentThread().getName()+":"+nums.remove(0)); } catch(Exception e){ continue ; } } } }
可見(jiàn)對(duì)于集合同步操作,使用Collections的同步包裝工具類,還需要對(duì)非原子操作用戶還需要手動(dòng)進(jìn)行同步
如下所示,加一個(gè)線程,對(duì)集合進(jìn)行讀取
class ReadListThread extends Thread { private List<Integer> nums; public ReadListThread(List<Integer> nums) { super(“ReadListThread”); this.nums = nums; } // 不停讀取元素,非原子操作,則需要手動(dòng)加上鎖 public void run() { while (true) { //休眠,將鎖交給其他線程 try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } synchronized (nums) { if (nums.size() > 100) { Iterator<Integer> iter = nums.iterator(); while (iter.hasNext()) { System.out.println(Thread.currentThread().getName() + ”:” + iter.next()); ; } } else{ try { nums.wait(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } } }
總結(jié)
以上就是本文關(guān)于java集合框架線程同步代碼詳解的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對(duì)本站的支持!
- Java基礎(chǔ)之集合框架詳解
- 簡(jiǎn)單了解java集合框架LinkedList使用方法
- Java集合框架Collections原理及用法實(shí)例
- 通過(guò)實(shí)例學(xué)習(xí)Java集合框架HashSet
- JAVA集合框架工具類自定義Collections集合方法
- 基于Java中最常用的集合類框架之HashMap(詳解)
- Java復(fù)習(xí)之集合框架總結(jié)
- Java集合框架LinkedList詳解及實(shí)例
- Java集合框架中迭代器Iterator解析
- Lambda表達(dá)式和Java集合框架
- Java集合的總體框架相關(guān)知識(shí)總結(jié)
相關(guān)文章
Springboot Thymeleaf實(shí)現(xiàn)HTML屬性設(shè)置
這篇文章主要介紹了Springboot Thymeleaf實(shí)現(xiàn)HTML屬性設(shè)置,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2007-11-11SpringBoot中OKHttp和壓縮文件的使用實(shí)戰(zhàn)教程
本文介紹了如何在SpringBoot中使用OKHttp發(fā)起請(qǐng)求和處理壓縮文件,包括文件的存儲(chǔ)配置、實(shí)體類、配置類和初始化類的設(shè)置,以及如何通過(guò)主程序和測(cè)試類進(jìn)行實(shí)際操作,最后提供了必要的依賴添加方法,以確保功能的實(shí)現(xiàn)2024-10-10myeclipse導(dǎo)出可運(yùn)行jar包簡(jiǎn)介
這篇文章主要介紹了myeclipse導(dǎo)出可運(yùn)行jar包簡(jiǎn)介,具有一定參考價(jià)值,需要的朋友可以了解下。2017-11-11Java8函數(shù)式編程應(yīng)用小結(jié)
Java8非常重要的就是引入了函數(shù)式編程的思想,使得這門經(jīng)典的面向?qū)ο笳Z(yǔ)言有了函數(shù)式的編程方式,彌補(bǔ)了很大程度上的不足,函數(shù)式思想在處理復(fù)雜問(wèn)題上有著更為令人稱贊的特性,本文給大家介紹Java8函數(shù)式編程應(yīng)用小結(jié),感興趣的朋友一起看看吧2023-12-12Java實(shí)現(xiàn)輸入流轉(zhuǎn)化為String
這篇文章主要介紹了Java實(shí)現(xiàn)輸入流轉(zhuǎn)化為String的相關(guān)資料,需要的朋友可以參考下2016-12-12elasticsearch節(jié)點(diǎn)的transport請(qǐng)求發(fā)送處理分析
這篇文章主要為大家介紹了elasticsearch節(jié)點(diǎn)的transport請(qǐng)求發(fā)送處理分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04Maven使用Nexus創(chuàng)建私服的實(shí)現(xiàn)
本文主要介紹了Maven使用Nexus創(chuàng)建私服的實(shí)現(xiàn),通過(guò)建立自己的私服,就可以降低中央倉(cāng)庫(kù)負(fù)荷、節(jié)省外網(wǎng)帶寬、加速M(fèi)aven構(gòu)建、自己部署構(gòu)件等,從而高效地使用Maven,感興趣的可以了解一下2024-04-04