【深入Java基础】HashMap的高级用法(二):同步
2018-01-30 18:07
405 查看
HashMap的高级用法:同步
HashMap是不支持同步的,不能用于多线程中。而HashTable是同步的,这个日后再论。我们可以使用以下两种方法来实现HashMap的同步:使用
ConcurrentHashMap
使用
Collections.synchronizedMap获取同步map
使用ConcurrentHashMap
ConcurrentHashMap<Integer,String> concurrentHashMap = new ConcurrentHashMap<>();
使用Collections.synchronizedMap获取同步map
HashMap<Integer,String> hashMap = new HashMap<>(); Map<Integer,String> synchronizedMap = Collections.synchronizedMap(hashMap);
测试
对于没有同步的HashMap在多线程中运行一定会抛出异常:
java.util.ConcurrentModificationException
运行两个线程同时对一个hashmap进行读写操作:
HashMap<Integer,String> hashMap1 = new HashMap<>(); //写线程 new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 1000; i++) { hashMap1.put(i,"value"+i); try { Thread.sleep(new Random().nextInt(10)); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); //读线程 new Thread(new Runnable() { @Override public void run() { while (true) { if (hashMap1.size() > 0) { for (Map.Entry entry : hashMap1.entrySet()) { System.out.println(entry.getKey() + "=" + entry.getValue()); } } try { Thread.sleep(new Random().nextInt(10)); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start();
运行以上代码抛出异常
java.util.ConcurrentModificationException。原因是未实现同步时,在迭代hashmap的时候不能修改数据。
Collections.synchronizedMap实现同步:
HashMap<Integer,String> hashMap1 = new HashMap<>(); Map<Integer, String> map = Collections.synchronizedMap(hashMap1); //写线程 new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 1000; i++) { map.put(i,"value"+i); try { Thread.sleep(new Random().nextInt(10)); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); //读线程 new Thread(new Runnable() { @Override public void run() { while (true) { if (map.size() > 0) { for (Map.Entry entry : map.entrySet()) { System.out.println(entry.getKey() + "=" + entry.getValue()); } } try { Thread.sleep(new Random().nextInt(10)); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start();
运行以上代码任然抛出异常
java.util.ConcurrentModificationException。可见该方法并不安全。(还是这样测试有问题?)
ConcurrentHashMap实现同步:
ConcurrentHashMap<Integer,String> concurrentHashMap = new ConcurrentHashMap<>();
//写线程
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
concurrentHashMap.put(i,"value"+i);
try {
Thread.sleep(new Random().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
//读线程
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
if (concurrentHashMap.size() > 0) {
ca59
for (Map.Entry entry : concurrentHashMap.entrySet()) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
}
try {
Thread.sleep(new Random().nextInt(10));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
运行以上代码,无异常。
所以为了保证多线程下的hashmap的数据一致性使用ConcurrentHashMap最为合理。并且ConcurrentHashMap的效率也比较高。为什么日后再论。
使用lock锁手动实现hashmap的同步:
ReentrantLock lock = new ReentrantLock(true); HashMap<Integer, String> hashMap1 = new HashMap<>(); //写线程 new Thread(new Runnable() { @Override public void run() { try { for (int i = 0; i < 1000; i++) { hashMap1.put(i, "value" + i); try { Thread.sleep(new Random().nextInt(10)); } catch (InterruptedException e) { e.printStackTrace(); } } } catch (Exception e) { } finally { //lock.unlock(); } } }).start(); //读线程 new Thread(new Runnable() { @Override public void run() { while (true) { lock.lock(); try { if (hashMap1.size() > 0) { for (Map.Entry entry : hashMap1.entrySet()) { System.out.println(entry.getKey() + "=" + entry.getValue()); } } } catch (Exception e) { System.out.println(e.getMessage()); } finally { lock.unlock(); } try { Thread.sleep(new Random().nextInt(10)); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start();
相关文章推荐
- 【深入Java基础】HashMap高级用法(一):排序
- 【深入Java基础】HashMap的基本用法
- 【深入Java基础】HashMap源码分析(二)
- java基础:HashMap、HashTable、LinkedHashMap和TreeMap用法和区别
- 【深入Java基础】HashMap总结
- 【Java基础】深入HashMap
- 【深入Java基础】ArrayList、LinkedList和Vector的用法与区别
- Java 枚举类型的基础和高级用法
- 深入Java基础(四)--哈希表(1)HashMap应用及源码详解
- 【深入Java基础】HashMap源码分析
- Java打开窗体基础用法
- JAVA正则表达式高级用法(分组与捕获)
- [零基础学JAVA]Java SE面向对象部分-15.面向对象高级(03) 推荐
- [零基础学JAVA]Java SE面向对象部分-13.面向对象高级(01) 推荐
- [零基础学JAVA]Java SE面向对象部分-18.面向对象高级(06) 推荐
- [零基础学JAVA]Java SE面向对象部分-19.面向对象高级(07) 推荐
- JAVA基础(异常/深入java.lang.Throwable)
- Java语言深入:深入研究Java equals方法,equals,==,equals用法
- 浅析Java多线程编程中的高级技术-Java基础-Java-编程开发
- 探索JDK1.5高级编码特征-Java基础-Java-编程开发