Java集合中的线程安全问题

介绍

JDK中提供了很多集合实现,本文不会介绍有哪些集合的接口以及实现类,而是介绍如何在多线程情况下使用这些集合。

阅读更多…

如果您还不太了解Java的整个集合体系的话,请查看《 Java开发成长之路第一年》。如果您还想要了解线程的相关内容,请查看《Java多线程》。
线程不安全

java.util.HashMap、java.util.ArrayList、java.util.LinkedList、java.util.HashSet等集合实现类都是线程不安全的,在多线程环境下使用的话,将会得到无法预期的结果。
遍历不安全

java.util.Hashtable、java.util.Vector等集合类在多线程环境下,如果只是调用put、get、remove等方法的话是能保证线程安全的,但如果进行遍历的话就无法保证线程安全了。这种情况也叫做“条件线程安全”。
线程安全

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

下面是验证HashMap问题的示例代码:
[codesyntax lang="java"]
import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;/** * java.util.HashMap的线程不安全测试,这里会有如下两种情况: *

    *
  • 输出的Map元素个数不对
  • *
  • 死循环(线程数多了更容易出现)
  • *
* @author suren * @date 2017年2月22日 下午3:31:09 /public class HashMapTest{ static Map map; public static void main(String[] args) { map = new HashMap(); long begin = System.currentTimeMillis(); ThreadGroup group = new ThreadGroup("HashMap thread test from surenpi.com"); List threadList = new ArrayList(); 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实现类的效率比较示例:
[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()); mapTest(new ConcurrentHashMap()); } static void mapTest(final Map map) { long begin = System.currentTimeMillis(); ThreadGroup group = new ThreadGroup("HashMap thread test from surenpi.com"); List threadList = new ArrayList(); 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的线程不安全测试,这里会有如下两种情况: *

    *
  • ArrayList可能会出现下标越界的异常
  • *
  • LinkedList的元素个数不正确
  • *
* @author suren * @date 2017年2月22日 下午3:31:09 */public class NonThreadSafeListTest{ public static void main(String[] args) { listTest(new LinkedList()); listTest(new ArrayList()); } static void listTest(final List list) { long begin = System.currentTimeMillis(); ThreadGroup group = new ThreadGroup("HashMap thread test from surenpi.com"); List threadList = new ArrayList(); 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]

你可能感兴趣的:(Java集合中的线程安全问题)