java集合框架線程同步代碼詳解
List接口的大小可變數(shù)組的實(shí)現(xiàn)。實(shí)現(xiàn)了所有可選列表操作,并允許包括null在內(nèi)的所有元素。除了實(shí)現(xiàn)List接口外,此類還提供一些方法來操作內(nèi)部用來存儲列表的數(shù)組的大小。(此類大致上等同于Vector類,除了此類是不同步的。)size、isEmpty、get、set、iterator和listIterator操作都以固定時(shí)間運(yùn)行。add操作以分?jǐn)偟墓潭〞r(shí)間運(yùn)行,也就是說,添加n個(gè)元素需要O(n)時(shí)間。其他所有操作都以線性時(shí)間運(yùn)行(大體上講)。與用于LinkedList實(shí)現(xiàn)的常數(shù)因子相比,此實(shí)現(xiàn)的常數(shù)因子較低。每個(gè)ArrayList實(shí)例都有一個(gè)容量。該容量是指用來存儲列表元素的數(shù)組的大小。它總是至少等于列表的大小。隨著向ArrayList中不斷添加元素,其容量也自動(dòng)增長。并未指定增長策略的細(xì)節(jié),因?yàn)檫@不只是添加元素會帶來分?jǐn)偣潭〞r(shí)間開銷那樣簡單。在添加大量元素前,應(yīng)用程序可以使用ensureCapacity操作來增加ArrayList實(shí)例的容量。這可以減少遞增式再分配的數(shù)量。
注意,此實(shí)現(xiàn)不是同步的。
如果多個(gè)線程同時(shí)訪問一個(gè)ArrayList實(shí)例,而其中至少一個(gè)線程從結(jié)構(gòu)上修改了列表,那么它必須保持外部同步。(結(jié)構(gòu)上的修改是指任何添加或刪除一個(gè)或多個(gè)元素的操作,或者顯式調(diào)整底層數(shù)組的大??;僅僅設(shè)置元素的值不是結(jié)構(gòu)上的修改。)這一般通過對自然封裝該列表的對象進(jìn)行同步操作來完成。如果不存在這樣的對象,則應(yīng)該使用Collections.synchronizedList方法將該列表“包裝”起來。這最好在創(chuàng)建時(shí)完成,以防止意外對列表進(jìn)行不同步的訪問:
Listlist=Collections.synchronizedList(newArrayList(...));
此類的iterator和listIterator方法返回的迭代器是快速失敗的:在創(chuàng)建迭代器之后,除非通過迭代器自身的remove或add方法從結(jié)構(gòu)上對列表進(jìn)行修改,否則在任何時(shí)間以任何方式對列表進(jìn)行修改,迭代器都會拋出ConcurrentModificationException。因此,面對并發(fā)的修改,迭代器很快就會完全失敗,而不是冒著在將來某個(gè)不確定時(shí)間發(fā)生任意不確定行為的風(fēng)險(xiǎn)。
注意,迭代器的快速失敗行為無法得到保證,因?yàn)橐话銇碚f,不可能對是否出現(xiàn)不同步并發(fā)修改做出任何硬性保證??焖偈〉鲿M最大努力拋出ConcurrentModificationException。因此,為提高這類迭代器的正確性而編寫一個(gè)依賴于此異常的程序是錯(cuò)誤的做法:迭代器的快速失敗行為應(yīng)該僅用于檢測bug。
如上所示,現(xiàn)在建立一個(gè)list集合,一個(gè)線程對集合進(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 ;
}
}
}
}
通過List<Integer>synNums=Collections.synchronizedList(nums);就能對原子操作進(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 ;
}
}
}
}
可見對于集合同步操作,使用Collections的同步包裝工具類,還需要對非原子操作用戶還需要手動(dòng)進(jìn)行同步
如下所示,加一個(gè)線程,對集合進(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集合框架線程同步代碼詳解的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
相關(guān)文章
Java+opencv3.2.0實(shí)現(xiàn)模板匹配
這篇文章主要為大家詳細(xì)介紹了Java+opencv3.2.0實(shí)現(xiàn)模板匹配的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02
SpringBoot整合MongoDB實(shí)現(xiàn)事務(wù)管理
Spring Boot是一種快速開發(fā)Spring應(yīng)用的方式,它提供了大量的自動(dòng)配置和默認(rèn)設(shè)置,以簡化開發(fā)流程,MongoDB是一個(gè)基于文檔的NoSQL數(shù)據(jù)庫,本文將介紹如何在Spring Boot應(yīng)用中整合MongoDB,并實(shí)現(xiàn)事務(wù)管理,需要的朋友可以參考下2024-07-07
詳解SpringBoot使用RedisTemplate操作Redis的5種數(shù)據(jù)類型
本文主要介紹了SpringBoot使用RedisTemplate操作Redis的5種數(shù)據(jù)類型,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
淺談@RequestParam(required = true)的誤區(qū)
這篇文章主要介紹了@RequestParam(required = true)的誤區(qū),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
Mybatis批量插入Oracle數(shù)據(jù)的方法實(shí)例
在開發(fā)中或多或少都會遇到數(shù)據(jù)批量插入的功能,最近我在做項(xiàng)目的過程中就遇到了這樣一個(gè)問題,下面這篇文章主要給大家介紹了關(guān)于Mybatis批量插入Oracle數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下2022-01-01

