作者微信 bishe2022

代码功能演示视频在页面下方,请先观看;如需定制开发,联系页面右侧客服
Map的并发处理(ConcurrentHashMap)

Custom Tab

参见:http://zl198751.iteye.com/blog/907927

 

ConcurrentModificationException

在这种迭代方式中,当iterator被创建后集合再发生改变就不再是抛出ConcurrentModificationException,取而代之的是在改变时new新的数据从而不影响原有的数据 ,iterator完成后再将头指针替换为新的数据 ,这样iterator线程可以使用原来老的数据,而写线程也可以并发的完成改变。

左边便是Hashtable的实现方式---锁整个hash表;而右边则是ConcurrentHashMap的实现方式---锁桶(或段)。 ConcurrentHashMap将hash表分为16个桶(默认值),诸如get,put,remove等常用操作只锁当前需要用到的桶。试想,原来只能一个线程进入,现在却能同时16个写线程进入(写线程才需要锁定,而读线程几乎不受限制,之后会提到),并发性的提升是显而易见的。

    更令人惊讶的是ConcurrentHashMap的读取并发,因为在读取的大多数时候都没有用到锁定,所以读取操作几乎是完全的并发操作,而写操作锁定的粒度又非常细,比起之前又更加快速(这一点在桶更多时表现得更明显些)。只有在求size等操作时才需要锁定整个表。而在迭代时,ConcurrentHashMap使用了不同于传统集合的快速失败迭代器(见之前的文章《JAVA API备忘---集合》)的另一种迭代方式,我们称为弱一致迭代器。在这种迭代方式中,当iterator被创建后集合再发生改变就不再是抛出ConcurrentModificationException,取而代之的是在改变时new新的数据从而不影响原有的数据,iterator完成后再将头指针替换为新的数据,这样iterator线程可以使用原来老的数据,而写线程也可以并发的完成改变,更重要的,这保证了多个线程并发执行的连续性和扩展性,是性能提升的关键。

 

示例:

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class MapConcurrenceDemo {
  private static Map<String, String> map = new HashMap<String, String>();
  static{
   for(int i=0;i<1000;i++){
    String str = String.valueOf(i);
    map.put(str, str);
   }
  }
  public static void main(String[] args) {
  new Thread(new MapListThread(map)).start();
  new Thread(new MapRemoveThread(map)).start();
}
}
class MapListThread implements Runnable{
 private Map<String, String> map;
 public MapListThread(Map<String, String> map){
  this.map = map;
 }
 public void run() {
  Iterator<String> iter = map.values().iterator();
  while(iter.hasNext()){
   iter.next();
   try {
    Thread.sleep(5);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
 }
}
class MapRemoveThread implements Runnable{
 private Map<String, String> map;
 public MapRemoveThread(Map<String, String> map){
  this.map = map;
 }
 public void run() {
  for(int i=200;i<900;i++){
   String str = String.valueOf(i);
   map.remove(str);
   try {
    Thread.sleep(5);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
  System.out.println("Remove OK. map.size:"+map.size());
 }
}

执行结果:

Exception in thread "Thread-0" java.util.ConcurrentModificationException
 at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
 at java.util.HashMap$ValueIterator.next(HashMap.java:822)
 at com.effective.object.MapListThread.run(MapConcurrenceDemo.java:29)
 at java.lang.Thread.run(Thread.java:619)
Remove OK. map.size:300

如果把map的实现类改为ConcurrentHashMap,就不会出现上面的错误,如下:

private static Map<String, String> map = new ConcurrentHashMap<String, String>();

转载自:http://blog.sina.com.cn/s/blog_6145ed810100yvng.html

Home