AJPFX总结OpenJDK 和 HashMap大量数据处理时,避免垃圾回收延迟的技巧二
HashMap简史
![]() H.P. Luhn (1896-1964)
|
Luhn 写道, “hashcode” 是基本的运算符。
Luhn 写道, “Associative Array” 是基本的运算数。
由此, ‘HashMap’ (也称为 HashTable) 就这样产生了。
注: HashMap 是由 1896 年出生的计算机科学家提出来的。HashMap 可是个老 家伙啦!
|
|
Niklaus Wirth 在他1976年编写的经典著作《算法 + 数据结构 = 程序》中,谈到对于所有的程序,都可以将“算法”视为基本的运算符,将“数据结构”视为基本的运算“数”。
从那时起,数据结构(HashMap,Heap等)发展缓慢。1987年有一个重大突破, Tarjan 提出了非常著名的 F-Heap;但除此之外,乏善可陈。要知道,HashMap 是1953年第一次提出的,已经过去60余年啦!
与此同时,算法方面 (Karmakar 1984, NegaMax 1989, AKS Primality 2002, Map-Reduce2006, Grover’s Quantum search - 2011) 则进展迅速,为计算的基础建设带来了崭新的、强大的运算符。
然而,现在到了2014,也许又轮到数据结构来取得重大进展了。从 OpenJDK 平台来看, 非堆 HashMap 就是一个正在发展的数据结构。
HashMap 的历史就介绍到这。下面我们来探索今天的 HashMap 吧。具体来说,我们先来看一看这个老家伙在 Java 中现存的 3 种实现。
java.util.HashMap (非线程安全) 对于任何真正的多线程并发用例,它会立即失败,而且是每次都会失败。所有用到它的代码必须使用 Java 内存模型(JMM)的内存屏障(memory barrier)策略(如 synchronized 或 volatile) 来保证顺序执行。
假设线程1写入 HashMap,那么它做出的改动只会保存在 CPU 1的1级缓存中。然后线程2,在几秒钟后开始在 CPU 2上运行;它读取 HashMap,是从 CPU 2的1级缓存中读出来的——它看不到线程1做出的改动,因为在读和写的线程中都没有读、写间的内存屏障,虽然 Java 内存模型要求线程共享 HashMap 的情形下必须要有。即使线程1的写操作加了 synchronize 也会失败,这样虽然能把它做出的改动写入到主内存中,但线程2仍然看不到这些改动,因为线程2只会从 CPU 2的1级缓存中读取。所以在写操作上加 synchronized 只能避免写操作的冲突。要对于所有的线程都添加必要的内存屏障,你必须也要 synchronize 读操作。
|
thrSafeHM = Collections.synchronizedMap(hm) ; (粗粒度锁定)

Collections.synchronizedMap() 返回一个 MT-Safe HashMap.
幸好这是完全同步的,不会真正的同步,隔离(isolation)=序列化(SERIALIZABLE)(总体上这是令人失望的)HashMap陷阱,我们期待的OpenJDK非堆存储(off-heap)JEP已经有一个 值得推荐的期待:硬件事务性内存(Hardware Transactional Memory (HTM))。关于HTM,粗粒度的同步写操作在Java中将会再一次变得很酷!就让HTM通过代码上的零并发和在硬件的零并发来帮助我们,实现真正的并发并且100%的多线程安全。这很酷,对吧?
java.util.concurrent.ConcurrentHashMap (线程安全、智能锁,但并非完美)

AJPFX总结OpenJDK 和 HashMap大量数据处理时,避免垃圾回收延迟的技巧二的更多相关文章
- OpenJDK与HashMap
OpenJDK的非堆JDK增强提议(JDK Enhancement-Proposal,JEP)试图标准化一项基础设施,它从Java6开始,只能在HotSpot和OpenJDK内部使用.这种设施能够像管 ...
- 大数据处理时用到maven的repository
由于做数据处理时,经常遇到maven 下载依赖包错误,下面我将自己下载好的repository 分享下 里边包含:Hadoop ,storm ,sprk ,kafka ,等 压缩后500多M. htt ...
- python数据处理技巧二
python数据处理技巧二(掌控时间) 首先简单说下关于时间的介绍其中重点是时间戳的处理,时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00 ...
- Java运行时内存划分与垃圾回收--以及类加载机制基础
----JVM运行时内存划分----不同的区域存储的内容不同,职责因为不同1.方法区:被线程共享,存储被JVM加载的类的信息,常量,静态变量等2.运行时常量池:属于方法区的一部分,存放编译时期产生的字 ...
- Java虚拟机运行时数据区域及垃圾回收算法
程序计数器 记录正在执行的虚拟机字节码指令的地址(如果正在执行的是本地方法则为空). Java 虚拟机栈 每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表.操作数栈.动态链接.方法出口 ...
- Java JVM运行时数据区,内存管理和GC垃圾回收
一 . 运行时数据区 程序计数器是线程私有的,是一块很小的内存空间,是当前线程执行到字节码行号的计数指示器.每个CPU处理器核心 在任何一个时刻,都只可能运行着唯一的一个线程,执行着一条指令.所以在多 ...
- JVM运行时数据区和垃圾回收机制
最近参考各种资料,尤其是<深入理解Java虚拟机 JVM高级特性和最佳实践>,大牛之作.把最近学习的Java虚拟机组成和垃圾回收机制总结一下. 你不会的都是新知识,学无止境,每天进步一点点 ...
- 《对“XXX::Invoke”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们》的问题的解决方法
<对“XXX::Invoke”类型的已垃圾回收委托进行了回调.这可能会导致应用程序崩溃.损坏和数据丢失.向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们& ...
- AJPFX浅谈Java 性能优化之垃圾回收(GC)
★JVM 的内存空间 在 Java 虚拟机规范中,提及了如下几种类型的内存空间: ◇栈内存(Stack):每个线程私有的.◇堆内存(Heap):所有线程公用的.◇方法区(Method Area):有点 ...
随机推荐
- unzip解压指定我文件夹
解压try.zip中指定的文件夹 unzip try.zip "try/*" shell中异常处理 { # your 'try' block executeCommandWhich ...
- BigDecimal快速使用
double类型最多支持16位有效数字,且最大值只支持10^308次方,大一点的数字会变为科学计数法,小数精度不够等有一系列不方便的问题: 引进BigDecimal解决此类麻烦,弊端,BigDecim ...
- springboot如何使用外部tomcat容器
一般情况spring-boot-starter-web是自带tomcat(即springboot内嵌tomcat),所以打包直接生成jar包,用java -jar命令就可以启动. 但,有时我们希望用w ...
- Android 图片着色 Tint 详解
问题描述 在app中可能存在一张图片只是因为颜色的不同而引入了多张图片资源的情况.比如 一张右箭头的图片,有白色.灰色和黑色三种图片资源存在.所以我们可不可以只保留一张基础图片,在此图片基础上只是颜色 ...
- hdu 2680 Choose the best route 解题报告
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2680 题目意思:实质就是给定一个多源点到单一终点的最短路. 卑鄙题---有向图.初始化map时 千万不 ...
- 创建app前的环境配置/AppIcon/启动图片
1.真机调试http://blog.csdn.net/tht2009/article/details/48580569 2.创建app前的环境配置
- c++11实现DLL帮助类
用过DLL的人都会发现,在C++中调用dll中的函数有点繁琐,调用过程如下:在加载dll后还要定义一个对应的函数指针类型,接着调用GetProcAddress获取函数地址,再转成函数指针,最后调用函数 ...
- 【CAIOJ1177】 子串是否出现
[题目链接] 点击打开链接 [算法] KMP [代码] #include<bits/stdc++.h> using namespace std; #define MAXA 1000010 ...
- liist不同遍历优缺点
JAVA中循环删除list中元素的方法总结 印象中循环删除list中的元素使用for循环的方式是有问题的,但是可以使用增强的for循环,然后今天在使用时发现报错了,然后去科普了一下,再然后发现这是一个 ...
- kubernetes1.13.1部署ingress-nginx-十一
一.Ingress 简介 (1) 在Kubernetes中,服务和Pod的IP地址仅可以在集群网络内部使用,对于集群外的应用是不可见的. 为了使外部的应用能够访问集群内的服务, 在Kubernetes ...

