介绍
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的线程不安全测试,这里会有如下两种情况: * <ul> * <li>输出的Map元素个数不对</li> * <li>死循环(线程数多了更容易出现)</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实现类的效率比较示例:
[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可能会出现下标越界的异常</li> * <li>LinkedList的元素个数不正确</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]