日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java 多线程集合操作_多线程中使用Java集合类

發布時間:2025/3/20 java 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 多线程集合操作_多线程中使用Java集合类 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Java集合類中,某個線程在 Collection 上進行迭代時,通常不允許另一個線性修改該 Collection。通常在這些情況下,迭代的結果是不確定的。如果檢測到這種行為,一些迭代器實現(包括 JRE 提供的所有通用 collection 實現)可能選擇拋出此異常。執行該操作的迭代器稱為快速失敗 迭代器,因為迭代器很快就完全失敗,而不會冒著在將來某個時間任意發生不確定行為的風險。

因此,當一個線程試圖ArrayList的數據的時候,另一個線程對ArrayList在進行迭代的,會出錯,拋出ConcurrentModificationException。

比如下面的代碼:

finalList?tickets?=newArrayList();

for(inti?=0;?i?<100000;?i++)?{

tickets.add("ticket?NO,"+?i);

}

System.out.println("start1...");

for(inti?=0;?i?<10;?i++)?{

Thread?salethread?=?newThread()?{

public?voidrun()?{

while(tickets.size()?>0)?{

tickets.remove(0);

System.out.println(Thread.currentThread().getId()+"Remove?0");

}

}

};

salethread.start();

}

System.out.println("start2...");

newThread()?{

public?voidrun()?{

for(String?s?:?tickets)?{

System.out.println(s);

}

}

}.start();

上述程序運行后,會在某處拋出異常:

java.util.ConcurrentModificationException  at java.util.ArrayList$Itr.checkForComodification(Unknown Source)  at java.util.ArrayList$Itr.next(Unknown Source)  at mytest.mytestpkg.Tj$2.run(Tj.java:138)

Vector是線程同步的,那么把ArrayList改成Vector是不是就對了呢?

答案是否定的,事實上,無論是ArrayList還是Vector,只要是實現Collection接口的,都要遵循fail-fast的檢測機制,即在迭代是時候,不能修改集合的元素。一旦發現違法這個規定就會拋出異常。

--------------------------------------------------------------------------------

事實上,Vector相對于ArrayList的線程同步,體現在對集合元素是否臟讀上。即ArrayList允許臟讀,而Vector特殊的機制,不會出現臟讀,但是效率會很差。

舉個例子,一個集合,有10個線程從該集合中刪除元素,那么每個元素只可能由一個線程刪除掉,不可能會出現一個元素被多個線程刪除的情況。

比如下面的代碼:

finalList?tickets?=newArrayList();

for(inti?=0;?i?<100000;?i++)?{

tickets.add("ticket?NO,"+?i);

}

System.out.println("start1...");

for(inti?=0;?i?<10;?i++)?{

Thread?salethread?=?newThread()?{

public?voidrun()?{

while(true)?{

if(tickets.size()>0)

System.out.println(Thread.currentThread().getId()+?tickets.remove(0));

else

break;

}

}

};

salethread.start();

}

for循環構造10個線程刪除同一個集合中的數據,理論上只能刪除100000次。但是運行完發現,輸出的刪除次數108494次,其中很多數據都是被多個線程刪除,比如下面的輸出片段:

17ticket NO,35721  14ticket NO,35699  11ticket NO,35721  18ticket NO,35721  17ticket NO,35729  11ticket NO,35729  14ticket NO,35729  17ticket NO,35729  14ticket NO,35734  17ticket NO,35734  13ticket NO,35721

可以看到35721,35729都被多個線程刪除。這事實上就是出現了臟讀。解決的辦法就是加鎖,使得同一時刻只有1個線程對ArrayList做操作。

修改代碼,synchronized關鍵字,讓得到鎖對象的線程才能運行,這樣確保同一時刻只有一個線程操作集合。

finalList?tickets?=newArrayList();

for(inti?=0;?i?<100000;?i++)?{

tickets.add("ticket?NO,"+?i);

}

System.out.println("start1...");

finalObject?lock=newObject();

for(inti?=0;?i?<10;?i++)?{

Thread?salethread?=?newThread()?{

public?voidrun()?{

while(true)?{

synchronized(lock)

{

if(tickets.size()>0)

System.out.println(Thread.currentThread().getId()+?tickets.remove(0));

else

break;

}

}

}

};

salethread.start();

}

這樣得到的結果就是準確的了。

當然,不使用synchronized關鍵字,而直接使用vector或者Collections.synchronizedList 也是同樣效果:

finalList?tickets?=java.util.Collections.synchronizedList(newArrayList());

finalList?tickets?=newVector();

vector和Collections.synchronizedList 都是線程同步的,避免的臟讀的出現。

posted on 2013-02-28 11:33 順其自然EVO 閱讀(175) 評論(0) ?編輯 ?收藏

總結

以上是生活随笔為你收集整理的java 多线程集合操作_多线程中使用Java集合类的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。