转载请注明出处:http://blog.csdn.net/xingjiarong/article/details/48046751
在多线程中,如果要并发的修改一个数据结构,那么很有可能会破坏这个数据结构。例如,一个线程可能要向一个散列表中插入一个元素,假如在调整各个桶之间的链接关系时被剥夺了控制权,而此时正好有另外一个线程正在遍历链表,则可能会产生异常或者死循环。
可以通过锁来保护共享的数据结构,但是选择线程安全的实现作为替代可能更容易一些。
任何集合类都可以通过使用同步包装器变成线程安全的:
List<E> synchArrayList = Collections.synchronizedList(new ArrayList<E>());
Map<K,V> synchMap = Collections.synchronizedList(new HasMap<K,V>());
结果集合的方法使用锁加以保护,提供线程安全的访问。
如果在另一个线程可能进行修改时要对集合进行迭代,任然需要使用封锁。
synchronized(synchHashMap)
{
Iterator<K> iter = synchHashMap.keySet().iterator();
while(iter.hasNext())
//遍历
}
如果使用for each 循环必须使用同样的代码,因为循环使用了迭代器。如果在迭代的过程中另一个线程修改集合,迭代器会失效,抛出ConcurrentModificationException异常,因此并发的修改可以被可靠的检测出来。
java.util.concurrent包提供了映像、有序集和队列的高效实现:ConcurrentHashMap、ConcurrentSkipListMap、ConcurrentLinkedQueue。这些集合通过复杂的算法,通过允许并发的访问数据结构的不同部分来使竞争极小化。
这些集合返回弱一致性的迭代器。这意味着迭代器不一定能反映出他们被构造之后的所有的修改,但是,他们不会将同一个值返回两次,也不会抛出ConcurrentModificationException的异常。
例如下面的例子:
import java.util.*;
import java.util.concurrent.*;
/*
* ConcurrentLinkedQueue是“线程安全”的队列,而LinkedList是非线程安全的。
*
* 下面是“多个线程同时操作并且遍历queue”的示例
* (01) 当queue是ConcurrentLinkedQueue对象时,程序能正常运行。
* (02) 当queue是LinkedList对象时,程序会产生ConcurrentModificationException异常。
*
* @author skywang
*/
public class Main {
// TODO: queue是LinkedList对象时,程序会出错。
//private static Queue<String> queue = new LinkedList<String>();
private static Queue<String> queue = new ConcurrentLinkedQueue<String>();
public static void main(String[] args) {
// 同时启动两个线程对queue进行操作!
new MyThread("ta").start();
new MyThread("tb").start();
}
private static void printAll() {
String value;
Iterator iter = queue.iterator();
while(iter.hasNext()) {
value = (String)iter.next();
System.out.print(value+", ");
}
System.out.println();
}
private static class MyThread extends Thread {
MyThread(String name) {
super(name);
}
@Override
public void run() {
int i = 0;
while (i++ < 6) {
// “线程名” + "-" + "序号"
String val = Thread.currentThread().getName()+i;
queue.add(val);
// 通过“Iterator”遍历queue。
printAll();
}
}
}
}
使用ConcurrentLinkedQueue时不会报错
使用LinkedList时产生错误:
版权声明:本文为博主原创文章,转载请注明出处,查看原文章,请访问:http://blog.csdn.net/xingjiarong
原文地址:http://blog.csdn.net/xingjiarong/article/details/48046751