一.线程不安全的HashMap

多线程环境下,使用HashMap进行put操作会引起死循环(jdk1.7 Entry链表形成环形数据结构),导致CPU利用率接近100%。

结构:数组 table[]+链表entry<k,v>
put 对key做hash
默认初始化数组长度 16
加载因子 0.75
扩容 大于16*0.75时
rehash
hash冲突:链表解决。原来的entry移出去,后来的进来,然后next指向原来的entry
线程不安全:多个线程扩容时闭环,引起死循环。
为什么会形成闭环:
线程1 A>B>C
线程2 B>A倒置。会变成A>B>A
解决:
1.8 红黑树:数组+链表+红黑树。阈值:8
hashmap扩容过程:
传入新的容量
初始化新的Entry数组,将数据转移到新的Entry数组里(遍历旧数组,取得每个元素,释放旧数组的引用,重新计算位置)
table属性引用新的entry数组
修改阈值
hash算法:取key的hashcode值,高位运算,取模运算
1.8的优化
1.resize时不需要重新计算hash,只要看看原来的hash新增的那个bit是0还是1。0的话索引没变,1的话索引变成原索引加oldcap。找到新数组下标,确定索引位置,增加随机性。
2.不会形成闭环,扩容时不再使用头插法改成尾插法。

二.效率低下的HashTable

多个线程访问HashTable的同步方法,会引起阻塞或轮询状态。

三.ConcurrentHashMap

jdk1.7 锁分段技术

数据分段存储,每段配一把锁,当一个线程访问其中一段时,其他线程也可访问其他段。

结构:Segment数组,每个数组下面维护HashEntry链表(存键值对)

http://www.importnew.com/28263.html

https://baijiahao.baidu.com/s?id=1607561719049934113&wfr=spider&for=pc

Java并发编程的艺术笔记(六)——HashMap、ConcurentHashMap的原理与实现的更多相关文章

  1. 多线程的通信和同步(Java并发编程的艺术--笔记)

    1. 线程间的通信机制 线程之间通信机制有两种: 共享内存.消息传递.   2. Java并发 Java的并发采用的是共享内存模型,Java线程之间的通信总是隐式执行,通信的过程对于程序员来说是完全透 ...

  2. Java并发编程的艺术笔记(五)——Java中的锁

    一.Lock接口的几个功能: 显示的获取和释放锁 尝试非阻塞的获取锁 能被中断的获取锁 超时获取锁 使用方式: Lock lock = new ReentrantLock(); lock.lock() ...

  3. Java并发编程的艺术笔记(七)——CountDownLatch、CyclicBarrier详解

    一.等待多线程完成的CountDownLatch CountDownLatch允许一个或多个线程等待其他线程完成操作,像加强版的join.(t.join()是等待t线程完成) 例: (1)开启多个线程 ...

  4. Java并发编程的艺术· 笔记(1)

    目录 1.volatile的原理 2.Synchonized 3.无锁-偏向锁-轻量级锁-重量级锁 4.Java实现原子操作 1.volatile的原理 如何保持可见性: 1)将当前处理器缓存行的数据 ...

  5. Java并发编程的艺术笔记(九)——FutureTask详解

    FutureTask是一种可以取消的异步的计算任务.它的计算是通过Callable实现的,多用于耗时的计算. 一.FutureTask的三种状态 二.get()和cancel()执行示意 三.使用 一 ...

  6. Java并发编程的艺术笔记(八)——线程池

    一.线程池的主要处理流程 ThreadPoolExecutor执行execute方法分下面4种情况. 1)如果当前运行的线程少于corePoolSize,则创建新线程来执行任务(注意,执行这一步需要获 ...

  7. Java并发编程的艺术笔记(三)——Thread.join()

    t.join()方法只会使主线程进入等待池并等待t线程执行完毕后才会被唤醒.并不影响同一时刻处在运行状态的其他线程.它能够使得t.join()中的t优先执行,当t执行完后才会执行其他线程.能够使得线程 ...

  8. Java并发编程的艺术笔记(二)——wait/notify机制

    一.概述 一个线程修改了一个对象的值,另一个线程感知到变化从而做出相应的操作.前者是生产者,后者是消费者. 等待/通知机制,是指一个线程A调用了对象O的wait()方法进入等待状态,而另一个线程B调用 ...

  9. Java并发编程的艺术笔记(一)——volatile和syncronized关键字

    一.线程间的通信 volatile和syncronized关键字 volatile 修饰变量,告知任何对该变量的访问必须从共享内存获取,对它的改变必须同步刷新至共享内存,由此保证可见性. syncro ...

随机推荐

  1. JS中this的4种绑定规则

    this ES6中的箭头函数采用的是词法作用域. 为什么要使用this:使API设计得更简洁且易于复用. this即不指向自身,也不指向函数的词法作用域. this的指向只取决于函数的调用方式 thi ...

  2. MVC 部署到服务器

    1.Nuget程序包管理 —>程序包管理控制台,运行以下命令即可:Update-Package Microsoft.AspNet.WebApi -reinstall 2.dll文件的缺少,覆盖

  3. POJ题解Sorting It All Out-传递丢包+倍增

    题目链接: http://poj.org/problem?id=1094 题目大意(直接从谷歌翻译上复制下来的): 描述 不同值的递增排序顺序是其中使用某种形式的小于运算符来将元素从最小到最大排序的顺 ...

  4. CentOS7部署kettle

    去官网下载kettle, 或者百度网盘下载(nnnk),解压到目录/opt/service/, 解压后的目录是data-integration kettle需要java环境才能运行,因此要安装Java ...

  5. 08 Json结构化Datetime时间以及保留中文

    错误描述: import json import datetime a = datetime.datetime.now() print(a) b = json.dumps(a) print(b) 如上 ...

  6. JS中的事件传播流程

    JS中的事件传播流程 1,Javascript与HTML之间的交互是通过事件实现的. 事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间. 可以使用侦听器来预定事件,以便事件发生时执行相应代码. 2 ...

  7. List的Select 和Select().tolist()

    List<Person> delp = new List<Person> { ,Name=,Sign= }, ,Name= ,Sign=}, }; delp.Select(u ...

  8. dedecms 调用内容页分页

    arc.archives.class.php $TRUEfilename = $this->GetTruePath().$fileFirst."_".$i.".&q ...

  9. Linux学习篇之OpenKM的安装(汉化)

    OpenKM是一个开放源代码的电子文档管理系统,它的特点是可用于大型公司或是中小企业, 适应性比较强. 并且在知识管理方面的加工,提供了更加灵活和成本较低的替代应用,下面讲一下搭建方法. 一.以下都是 ...

  10. linux工具之pmap

    1.pmap简介 pmap命令用来报告一个进程或多个进程的内存映射.可以使用这个工具确定系统是如何为服务器上的进程分配内存的.   例如查看ssh进程的内存映射: