ConcurrentHashMap遍历详解
来源:互联网 发布:linux 复制文件覆盖 编辑:程序博客网 时间:2024/05/17 23:17
近期校招面试,问到ConcurrentHashMap遍历问题,今天总结下:
在ConcurrentHashMap中,使用了分段锁机制,所以任意数量的读线程可以并发访问Map、读操作和写操作的线程可以并发访问Map、并且一定数量(默认是使用16个锁)的写线程也可以并发修改Map。ConcurrentHashMap提供的迭代器不会抛出ConcurrentModificationExeption,而且具有弱一致性,它可以容忍并发的修改。当创建迭代器时会遍历已有的元素,并可以(但是不保证)在迭代器被构造后将修改操作反映给容器。
那么,当多个线程同时迭代一个ConcurrentHashMap的时候会发生什么呢?在遍历的时候更新又会发生什么呢?
1,多个线程可以同时迭代ConcurrentHashMap;
2,ConcurrentHashMap保证遍历的时候更新元素不会break(这正是并发容器的意义所在),但是不能保证数据的一致性,而迭代器保证的是:它反映的是创建迭代器时容器的状态。
注意:
从ConcurrentHashMap那里得到的iterator是为单线程设计的,即不可以传递它们,每一个线程都必须有自己的iterator。
例子:
(1)两个读线程和一个修改线程,每个线程各自拥有一个Iterator,并发访问ConcurrentHashMap。
import java.util.Map;import java.util.Random;import java.util.UUID;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ConcurrentMapIteration{ private final Map<String, String> map = new ConcurrentHashMap<String, String>(); private final static int MAP_SIZE = 100000; public static void main(String[] args) { new ConcurrentMapIteration().run(); } public ConcurrentMapIteration() { for (int i = 0; i < MAP_SIZE; i++) { map.put("key" + i, UUID.randomUUID().toString()); } } private final ExecutorService executor = Executors.newCachedThreadPool(); private final class Accessor implements Runnable { private final Map<String, String> map; public Accessor(Map<String, String> map) { this.map = map; } @Override public void run() { for (Map.Entry<String, String> entry : this.map.entrySet()) { System.out.println( Thread.currentThread().getName() + " - [" + entry.getKey() + ", " + entry.getValue() + ']' ); } } } private final class Mutator implements Runnable { private final Map<String, String> map; private final Random random = new Random(); public Mutator(Map<String, String> map) { this.map = map; } @Override public void run() { for (int i = 0; i < 100; i++) { this.map.remove("key" + random.nextInt(MAP_SIZE)); this.map.put("key" + random.nextInt(MAP_SIZE), UUID.randomUUID().toString()); System.out.println(Thread.currentThread().getName() + ": " + i); } } } private void run() { Accessor a1 = new Accessor(this.map); Accessor a2 = new Accessor(this.map); Mutator m = new Mutator(this.map); executor.execute(a1); executor.execute(m); executor.execute(a2); }}
结果:正常运行
(2)两个读线程共享一个Iterator
import java.util.Iterator;import java.util.Map;import java.util.Random;import java.util.UUID;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ConcurrentMapIteration{ private final Map<String, String> map = new ConcurrentHashMap<String, String>(); private final Iterator<Map.Entry<String, String>> iterator; private final static int MAP_SIZE = 100000; public static void main(String[] args) { new ConcurrentMapIteration().run(); } public ConcurrentMapIteration() { for (int i = 0; i < MAP_SIZE; i++) { map.put("key" + i, UUID.randomUUID().toString()); } this.iterator = this.map.entrySet().iterator(); } private final ExecutorService executor = Executors.newCachedThreadPool(); private final class Accessor implements Runnable { private final Iterator<Map.Entry<String, String>> iterator; public Accessor(Iterator<Map.Entry<String, String>> iterator) { this.iterator = iterator; } @Override public void run() { while(iterator.hasNext()) { Map.Entry<String, String> entry = iterator.next(); try { String st = Thread.currentThread().getName() + " - [" + entry.getKey() + ", " + entry.getValue() + ']'; } catch (Exception e) { e.printStackTrace(); } } } } private final class Mutator implements Runnable { private final Map<String, String> map; private final Random random = new Random(); public Mutator(Map<String, String> map) { this.map = map; } @Override public void run() { for (int i = 0; i < 100; i++) { this.map.remove("key" + random.nextInt(MAP_SIZE)); this.map.put("key" + random.nextInt(MAP_SIZE), UUID.randomUUID().toString()); } } } private void run() { Accessor a1 = new Accessor(this.iterator); Accessor a2 = new Accessor(this.iterator); Mutator m = new Mutator(this.map); executor.execute(a1); executor.execute(m); executor.execute(a2); }}
结果:发生死锁
(3)读线程和修改线程共享一个Iterator
import java.util.Iterator;import java.util.Map;import java.util.Random;import java.util.UUID;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ConcurrentMapIteration{ private final Map<String, String> map = new ConcurrentHashMap<String, String>(); private final Iterator<Map.Entry<String, String>> iterator; private final static int MAP_SIZE = 100000; public static void main(String[] args) { new ConcurrentMapIteration().run(); } public ConcurrentMapIteration() { for (int i = 0; i < MAP_SIZE; i++) { map.put("key" + i, UUID.randomUUID().toString()); } this.iterator = this.map.entrySet().iterator(); } private final ExecutorService executor = Executors.newCachedThreadPool(); private final class Accessor implements Runnable { private final Iterator<Map.Entry<String, String>> iterator; public Accessor(Iterator<Map.Entry<String, String>> iterator) { this.iterator = iterator; } @Override public void run() { while (iterator.hasNext()) { Map.Entry<String, String> entry = iterator.next(); try { String st = Thread.currentThread().getName() + " - [" + entry.getKey() + ", " + entry.getValue() + ']'; } catch (Exception e) { e.printStackTrace(); } } } } private final class Mutator implements Runnable { private final Random random = new Random(); private final Iterator<Map.Entry<String, String>> iterator; private final Map<String, String> map; public Mutator(Map<String, String> map, Iterator<Map.Entry<String, String>> iterator) { this.map = map; this.iterator = iterator; } @Override public void run() { while (iterator.hasNext()) { try { iterator.remove(); this.map.put("key" + random.nextInt(MAP_SIZE), UUID.randomUUID().toString()); } catch (Exception ex) { ex.printStackTrace(); } } } } private void run() { Accessor a1 = new Accessor(this.iterator); Accessor a2 = new Accessor(this.iterator); Mutator m = new Mutator(map, this.iterator); executor.execute(a1); executor.execute(m); executor.execute(a2); }}
结果:抛出java.lang.IllegalStateException异常。
- ConcurrentHashMap遍历详解
- ConcurrentHashMap详解
- ConcurrentHashMap详解
- ConcurrentHashMap详解
- ConcurrentHashMap详解
- ConcurrentHashMap详解
- ConcurrentHashMap详解
- ConcurrentHashMap详解
- ConcurrentHashMap详解
- ConcurrentHashMap详解
- ConcurrentHashMap详解
- conCurrentHashMap详解
- java concurrentHashMap 的详解
- ConcurrentHashMap 原理详解
- Java ConcurrentHashMap 详解
- ConcurrentHashMap原理详解
- ConcurrentHashMap原理详解
- ConcurrentHashMap原理详解
- 如何解决css样式表在不同浏览器中显示效果不同的问题
- 经典算法之活动选择问题
- C++中的单继承与多继承(上)
- 关于srand(time(0)) rand() 的解释
- WPS自动生成目录
- ConcurrentHashMap遍历详解
- 【学习笔记】网络编程基础API
- Socket bind failed: [730048]异常的处理
- java非常有用的代码段(关键时候可以看看)
- XML、JSON数据互转 在线快速互转网址
- Django URL解析的一些注意点
- python字符串操作
- jquery validate 详解一
- win下mongodb安装