JAVA线程安全Map解析

  • HashTable
    • 结构
    • 线程安全的实现
  • Collections.synchronizedMap
    • 线程安全的实现
  • ConcurrentHashMap
    • 线程安全的实现
      • ConcurrentHashMap的结构
      • 线程安全的具体实现
      • 经过hash计算,指定下标没有数据
      • 经过hash计算,发生Hash碰撞
      • 代码实现
  • JAVA集合目录

HashTable

结构

采用的是数组加上链表组成,链表部分插入为尾插。

线程安全的实现

对所有的操作方法进行加锁。

    public synchronized V put(K key, V value) {// Make sure the value is not nullif (value == null) {throw new NullPointerException();}// Makes sure the key is not already in the hashtable.Entry<?,?> tab[] = table;int hash = key.hashCode();int index = (hash & 0x7FFFFFFF) % tab.length;@SuppressWarnings("unchecked")Entry<K,V> entry = (Entry<K,V>)tab[index];for(; entry != null ; entry = entry.next) {if ((entry.hash == hash) && entry.key.equals(key)) {V old = entry.value;entry.value = value;return old;}}addEntry(hash, key, value, index);return null;}public synchronized V remove(Object key) {Entry<?,?> tab[] = table;int hash = key.hashCode();int index = (hash & 0x7FFFFFFF) % tab.length;@SuppressWarnings("unchecked")Entry<K,V> e = (Entry<K,V>)tab[index];for(Entry<K,V> prev = null ; e != null ; prev = e, e = e.next) {if ((e.hash == hash) && e.key.equals(key)) {modCount++;if (prev != null) {prev.next = e.next;} else {tab[index] = e.next;}count--;V oldValue = e.value;e.value = null;return oldValue;}}return null;}

Collections.synchronizedMap

线程安全的实现

使用java.util.Collections.SynchronizedMap代理类,把线程不安全的Map代理成线程安全的Map,在所有的方法上添加同步锁实现。

ConcurrentHashMap

线程安全的实现

  • CAS操作
  • 局部加锁

ConcurrentHashMap的结构


ConcurrentHashMap的结构由数组、链表、红黑树组成。

线程安全的具体实现

经过hash计算,指定下标没有数据

通过CAS替换。

经过hash计算,发生Hash碰撞

对该节点链表或者是红黑树的头节点进行加锁。

代码实现

final V putVal(K key, V value, boolean onlyIfAbsent) {if (key == null || value == null) throw new NullPointerException();int hash = spread(key.hashCode());int binCount = 0;for (Node<K,V>[] tab = table;;) {Node<K,V> f; int n, i, fh;if (tab == null || (n = tab.length) == 0)tab = initTable();// 如果原有的数组为空,直接使用cas进行替换即可else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {if (casTabAt(tab, i, null,new Node<K,V>(hash, key, value, null)))break;                   // no lock when adding to empty bin}// 如果正在扩容、多线程帮忙扩容else if ((fh = f.hash) == MOVED)tab = helpTransfer(tab, f);else {V oldVal = null;// 对头结点进行加锁synchronized (f) {if (tabAt(tab, i) == f) {if (fh >= 0) {binCount = 1;for (Node<K,V> e = f;; ++binCount) {K ek;if (e.hash == hash &&((ek = e.key) == key ||(ek != null && key.equals(ek)))) {oldVal = e.val;if (!onlyIfAbsent)e.val = value;break;}Node<K,V> pred = e;if ((e = e.next) == null) {pred.next = new Node<K,V>(hash, key,value, null);break;}}}else if (f instanceof TreeBin) {Node<K,V> p;binCount = 2;if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,value)) != null) {oldVal = p.val;if (!onlyIfAbsent)p.val = value;}}}}if (binCount != 0) {// 列百年的数据长度大于等于8、转换为红黑树if (binCount >= TREEIFY_THRESHOLD)treeifyBin(tab, i);if (oldVal != null)return oldVal;break;}}}addCount(1L, binCount);return null;}

JAVA集合目录

java集合目录

JAVA线程安全Map解析相关推荐

  1. 四种Java线程池用法解析

    四种Java线程池用法解析 本文为大家分析四种Java线程池用法,供大家参考,具体内容如下 http://www.jb51.net/article/81843.htm 1.new Thread的弊端 ...

  2. Java线程状态完全解析教程

    简介 Java线程有6种状态,分别是NEW.RUNNABLE.BLOCKED.WAITING.TIMED_WAITING.TERMINATED.本文讲解线程状态变化的流程以及用代码演示通过调用哪些方法 ...

  3. 面试题:四种Java线程池用法解析 !=!=未看

    1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? 1 2 3 4 5 6 7 8 new Thread(new Runnable() {   @Override   ...

  4. Java开发中Netty线程模型原理解析!

    Java开发中Netty线程模型原理解析,Netty是Java领域有名的开源网络库具有高性能和高扩展性的特点,很多流行的框架都是基于它来构建.Netty 线程模型不是一成不变的,取决于用户的启动参数配 ...

  5. java+线程安全的hash,多线程下HashMap安全问题-ConcurrentHashMap解析

    Java1.5 引入了 java.util.concurrent 包,其中 Collection 类的实现允许在运行过程中修改集合对象.实际上, Java 的集合框架是[迭代器设计模式]的一个很好的实 ...

  6. Java 调用Google Map Api解析地址,解析经纬度实例

    Java 调用Google Map Api解析地址,解析经纬度实例 使用google地图的反向地址解析功能,提供一个经纬度得到对应地址,或者给出模糊地址,得到经纬度,放在java后台代码中处理,这个使 ...

  7. Java Executor源码解析(3)—ThreadPoolExecutor线程池execute核心方法源码【一万字】

    基于JDK1.8详细介绍了ThreadPoolExecutor线程池的execute方法源码! 上一篇文章中,我们介绍了:Java Executor源码解析(2)-ThreadPoolExecutor ...

  8. java任务流程_死磕 java线程系列之线程池深入解析——普通任务执行流程

    (手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本. 注:线程池源码部分如无特殊说明均指ThreadPoolExecutor类. 简介 前面我们一起学习了Java中 ...

  9. Java线程池源码解析及高质量代码案例

    引言 本文为Java高级编程中的一些知识总结,其中第一章对Jdk 1.7.0_25中的多线程架构中的线程池ThreadPoolExecutor源码进行架构原理介绍以及源码解析.第二章则分析了几个违反J ...

最新文章

  1. 交互式讲解傅里叶变换
  2. table布局注意点
  3. 理解Java动态代理(1)—找我还钱?我出钱要你的命
  4. python绘制散点图-Python:matplotlib绘制散点图
  5. slf4j 如何返回堆栈_重学JS系列 - JS 调用堆栈
  6. linux 64 nc,linux 命令之nc
  7. spark-jar冲突解决方案
  8. HTML、CSS规范
  9. 图论 —— 图的连通性 —— Tarjan 缩点
  10. sed的模式匹配用法探讨
  11. 洛谷——P1046 [NOIP2005 普及组] 陶陶摘苹果
  12. Win10 镜像安装到新固态硬盘两法
  13. git cherry-pick 的使用
  14. php postgresql 参数,从postgresql函数参数中检索php数组键和值以进行数据库更新
  15. 豆瓣250排行榜算法
  16. 京东EB级全域大数据平台的演进与治理历程
  17. html怎样做修改密码的网页,HTML登录界面 html登录界面设置账号密码
  18. kubernetes 从入门到实践
  19. Matlab散点图进阶——矩阵气泡图
  20. 永远不要在MySQL中使用UTF-8

热门文章

  1. 用ATL创建COM组件及实例讲解
  2. 微信小程序-会议OA项目03
  3. list列表 python
  4. android 怎么导入项目,Android Studio怎么导入项目?
  5. 一、Kubernetes (k8s) 是什么, 有什么用?
  6. php取指定时间毫秒数,PHP取毫秒时间戳 microtime()
  7. Java咖啡馆(5)——Java语言基础
  8. 【无标题】尤破金12.1黄金还会跌吗?黄金原油行情趋势分析及晚间走势预测
  9. LeafletJS 简单使用3(超图使用问题解决) - 继1/2出现的问题及解决(超图更换地图地址之后瓦片空白问题解决)
  10. 用Python画一个小猪佩奇