Java集合中的線程安全問題

介紹

JDK中提供了很多集合實(shí)現(xiàn),本文不會介紹有哪些集合的接口以及實(shí)現(xiàn)類,而是介紹如何在多線程情況下使用這些集合。

閱讀更多…

如果您還不太了解Java的整個集合體系的話,請查看《Java開發(fā)成長之路第一年》。如果您還想要了解線程的相關(guān)內(nèi)容,請查看《Java多線程》。
線程不安全

java.util.HashMap、java.util.ArrayList、java.util.LinkedList、java.util.HashSet等集合實(shí)現(xiàn)類都是線程不安全的,在多線程環(huán)境下使用的話,將會得到無法預(yù)期的結(jié)果。
遍歷不安全

java.util.Hashtable、java.util.Vector等集合類在多線程環(huán)境下,如果只是調(diào)用put、get、remove等方法的話是能保證線程安全的,但如果進(jìn)行遍歷的話就無法保證線程安全了。這種情況也叫做“條件線程安全”。
線程安全

java.util.concurrent.ConcurrentHashMap、java.util.concurrent.CopyOnWriteArrayList、java.util.concurrent.ConcurrentArraySet等是線程安全的。
Map

下面是驗(yàn)證HashMap問題的示例代碼:
[codesyntax lang="java"]
import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;/** * java.util.HashMap的線程不安全測試,這里會有如下兩種情況: * <ul> * <li>輸出的Map元素個數(shù)不對</li> * <li>死循環(huán)(線程數(shù)多了更容易出現(xiàn))</li> * </ul> * @author suren * @date 2017年2月22日 下午3:31:09 /public class HashMapTest{ static Map<String, String> map; public static void main(String[] args) { map = new HashMap<String, String>(); long begin = System.currentTimeMillis(); ThreadGroup group = new ThreadGroup("HashMap thread test from surenpi.com"); List<Thread> threadList = new ArrayList<Thread>(); int threadCount = 10; for(int i = 0; i < threadCount; i++) { Thread thread = new Thread(group, new Runnable() { @Override public void run() { for(int j = 0; j < 200 ; j++) { map.put(Thread.currentThread().getName() + j, ""); map.get(Thread.currentThread().getName() + j); } } }); threadList.add(thread); } for(Thread thread : threadList) { thread.start(); } while(group.activeCount() > 0) {} System.out.println(map.size()); System.out.println("take time : " + (System.currentTimeMillis() - begin)); }}
[/codesyntax]
以下是線程安全的Map實(shí)現(xiàn)類的效率比較示例:
[codesyntax lang="java"]
import java.util.ArrayList;import java.util.Hashtable;import java.util.List;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;/
* * Hashtable和ConcurrentHashMap效率比較 * @author suren * @date 2017年2月22日 下午4:27:56 /public class ThreadSafeMapTest{ /* * @param args */ public static void main(String[] args) { mapTest(new Hashtable<String, String>()); mapTest(new ConcurrentHashMap<String, String>()); } static void mapTest(final Map<String, String> map) { long begin = System.currentTimeMillis(); ThreadGroup group = new ThreadGroup("HashMap thread test from surenpi.com"); List<Thread> threadList = new ArrayList<Thread>(); int threadCount = 10; for(int i = 0; i < threadCount; i++) { Thread thread = new Thread(group, new Runnable() { @Override public void run() { for(int j = 0; j < 9999 ; j++) { map.put(Thread.currentThread().getName() + j, ""); map.get(Thread.currentThread().getName() + j); } } }); threadList.add(thread); } for(Thread thread : threadList) { thread.start(); } while(group.activeCount() > 0) {} System.out.println(map.getClass() + " take time : " + (System.currentTimeMillis() - begin)); }}
[/codesyntax]
List

下面是ArrayList和LinkedList線程不安全的示例代碼:
[codesyntax lang="java"]
import java.util.ArrayList;import java.util.LinkedList;import java.util.List;/** * java.util.LinkedList和java.util.ArrayList的線程不安全測試,這里會有如下兩種情況: * <ul> * <li>ArrayList可能會出現(xiàn)下標(biāo)越界的異常</li> * <li>LinkedList的元素個數(shù)不正確</li> * </ul> * @author suren * @date 2017年2月22日 下午3:31:09 */public class NonThreadSafeListTest{ public static void main(String[] args) { listTest(new LinkedList<String>()); listTest(new ArrayList<String>()); } static void listTest(final List<String> list) { long begin = System.currentTimeMillis(); ThreadGroup group = new ThreadGroup("HashMap thread test from surenpi.com"); List<Thread> threadList = new ArrayList<Thread>(); int threadCount = 10; for(int i = 0; i < threadCount; i++) { Thread thread = new Thread(group, new Runnable() { @Override public void run() { for(int j = 0; j < 200 ; j++) { list.add(Thread.currentThread().getName() + j); } } }); threadList.add(thread); } for(Thread thread : threadList) { thread.start(); } while(group.activeCount() > 0) {} System.out.println(list.size()); System.out.println(list.getClass() + " take time : " + (System.currentTimeMillis() - begin)); }}
[/codesyntax]

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一. Java基礎(chǔ)部分.................................................
    wy_sure閱讀 3,995評論 0 11
  • 不足的地方請大家多多指正,如有其它沒有想到的常問面試題請大家多多評論,一起成長,感謝!~ String可以被繼承嗎...
    啟示錄是真的閱讀 3,065評論 3 3
  • 轉(zhuǎn)載自:Java集合框架實(shí)例 1- 介紹 集合是程序和語言的基本思想。應(yīng)用程序通常都會應(yīng)用到集合,例如雇員的信息,...
    01_小小魚_01閱讀 478評論 0 1
  • 1.import static是Java 5增加的功能,就是將Import類中的靜態(tài)方法,可以作為本類的靜態(tài)方法來...
    XLsn0w閱讀 1,419評論 0 2
  • 小編費(fèi)力收集:給你想要的面試集合 1.C++或Java中的異常處理機(jī)制的簡單原理和應(yīng)用。 當(dāng)JAVA程序違反了JA...
    八爺君閱讀 5,172評論 1 114

友情鏈接更多精彩內(nèi)容