并发数据结构
- 常用的数据结构是线程不安全的
– ArrayList,HashMap,HashSet 非同步的
– 多个线程同时读写这些数据结构时,可能会抛出异常或者数据错误 - 传统的Vector,Hashtable等同步的集合性能过差
- 并发的数据结构:数据添加或者删除
– 阻塞式集合:当集合为空或者满时,等待
– 非阻塞式集合:放集合为空或者满时,不等待,返回null或异常
List
- Vector 同步安全,写多读少
- ArrayList 不安全
Collections.synchronizedList(List list)
这个方法,将线程不安全的变成线程安全的, 基于synchronized(所包围的代码一次只能一个线程进入),效率差- JAVA 5开始,提供
CopyOnWriteArrayList
这个类,读多写少,基于复制机制的一个并发链表类,是非阻塞
Set
- HashSet 不安全
Collections.synchronizedSet(Set set)
方法,将线程不安全变成线程安全的,基于synchronized,效率差CopyOnWriteArraySet
(基于CopyOnWriteArrayList
),读多写少,非阻塞,线程安全的
Map
- Hashtable 同步安全,写多读少,性能不太行
- HashMap 不安全
Collections.synchronizedMap(Map map)
方法,基于synchronized,效率差ConcurrentHashMap
,读多写少,非阻塞,线程安全
Queue/Deque(队列,jdk1.5)
- ConcurrentLinkedQueue 非阻塞
- ArrayBlockingQueue/LinkedBlockingQueue 阻塞
用三种方法创建三个list,三个list传入三个线程类对象,每一个线程类对象创建十个线程,线程run方法是向list插入十个数,这样 每个list中就有100个数字。发现ArrayList创建的list中,数字的插入发生错误,线程不安全,其他俩种都是正确的。
其他的数据结构也类似
public class ListTest {
public static void main(String[] args) throws InterruptedException{
//线程不安全
List<String> unsafeList = new ArrayList<String>();
//线程安全
List<String> safeList1 = Collections.synchronizedList(new ArrayList<String>());
//线程安全
CopyOnWriteArrayList<String> safeList2 = new CopyOnWriteArrayList<String>();
ListThread t1 = new ListThread(unsafeList);
ListThread t2 = new ListThread(safeList1);
ListThread t3 = new ListThread(safeList2);
for(int i = 0; i < 10; i++){
Thread t = new Thread(t1, String.valueOf(i));
t.start();
}
for(int i = 0; i < 10; i++) {
Thread t = new Thread(t2, String.valueOf(i));
t.start();
}
for(int i = 0; i < 10; i++) {
Thread t = new Thread(t3, String.valueOf(i));
t.start();
}
//等待子线程执行完
Thread.sleep(2000);
System.out.println("listThread1.list.size() = " + t1.list.size());
System.out.println("listThread2.list.size() = " + t2.list.size());
System.out.println("listThread3.list.size() = " + t3.list.size());
//输出list中的值
System.out.println("unsafeList:");
for(String s : t1.list){
if(s == null){
System.out.print("null ");
}
else
{
System.out.print(s + " ");
}
}
System.out.println();
System.out.println("safeList1:");
for(String s : t2.list){
if(s == null){
System.out.print("null ");
}
else
{
System.out.print(s + " ");
}
}
System.out.println();
System.out.println("safeList2:");
for(String s : t3.list){
if(s == null){
System.out.print("null ");
}
else
{
System.out.print(s + " ");
}
}
}
}
class ListThread implements Runnable{ //线程类,向list添加元素
public List<String> list;
public ListThread(List<String> list){
this.list = list;
}
@Override
public void run() {
int i = 0;
while(i<10)
{
try {
Thread.sleep(10);
}catch (InterruptedException e){
e.printStackTrace();
}
//把当前线程名称加入list中
list.add(Thread.currentThread().getName());
i++;
}
}
}
//输出
listThread1.list.size() = 87
listThread2.list.size() = 100
listThread3.list.size() = 100
unsafeList:
null null 1 0 9 8 7 6 5 4 null null null 0 5 null null null 6 8 2 0 null ......
safeList1:
8 7 9 6 5 4 3 2 1 0 0 1 2 4 3 5 6 7 8 9 9 8 7 6 5 3 4 2 1 0 0 9 ......
safeList2:
0 6 7 8 4 1 3 5 2 9 0 2 6 5 1 3 9 8 7 4 0 7 8 3 2 9 6 5 4 1 0 5 ....