- 浏览: 113058 次
- 性别:
- 来自: 江西
文章分类
- 全部博客 (79)
- java (8)
- java虚拟机 (3)
- 学习类 (4)
- Java SE (26)
- java引用 (1)
- 工作总结。 (2)
- JSF (1)
- 软件架构 (1)
- Javascript (10)
- struts2 (1)
- eclipse (1)
- mysql (1)
- ArcGis (4)
- dojo (1)
- Extjs (1)
- jquery (4)
- 软件包 (1)
- 控件 (1)
- tuijian (0)
- 命令 (1)
- JAVAEE (1)
- goagent教程详细版猫理会 (0)
- python (0)
- tomcat (1)
- eclipse 出 can not create virtual machine (1)
- spring (3)
- 设计模式 (3)
- hibernate (1)
- dd (0)
- 样式 (0)
- http://blog.csdn.net/wisgood/article/details/11762427 (0)
最新评论
-
bz5011:
node.eachChild() 要延迟,等node.expa ...
EXTJS学习笔记----EXTJs中带复选框的tree,选中父节点时所有子节点也被选中 -
hvang1988:
[img][/img][url][/url][flash= ...
jquey 取值 -
xiaguangme:
写的很不错
java需要关注的知识点---HashMap -
perfect613:
sinly 写道perfect613 写道你好,有个问题请教一 ...
JS动态创建表格,动态设置属性,动态添加事件 . -
aiyingpower:
把哥的代码拿过来也不注明一下?
arcgis地图————————基础操作
ConcurrentHashMap默认初始大小 16,临界值:12:基数:0.75
1.ConcurrentHashMap是一个线程安全的hashMap。相对hashMap多出以下一些特殊属性:
2.ConcurrentHashMap的链表实例HashEntry:
这里需要注意的是Value,value并不是final的,而是一个volatile.
volatile修饰符告诉编译程序不要对该变量所参与的操作进行某些优化。在两种特殊的情况下需要使用volatile修饰符:
第一种情况涉及到内存映射硬件(memory-mapped hardware,如图形适配器,这类设备对计算机来说就好象是内存的一部分一样),
第二种情况涉及到共享内存(shared memory,即被两个以上同时运行的程序所使用的内存)。
大多数计算机拥有一系列寄存器,其存取速度比计算机主存更快。好的编译程序能进行一种被称为“冗余装入和存储的删去”(redundant load and store removal)的优化,即编译程序会在程序中寻找并删去这样两类代码:一类是可以删去的从内存装入数据的指令,因为相应的数据已经被存放在寄存器中;另一种是可以删去的将数据存入内存的指令,因为相应的数据在再次被改变之前可以一直保留在寄存器中。
如果一个指针变量指向普通内存以外的位置,如指向一个外围设备的内存映射端口,那么冗余装入和存储的优化对它来说可能是有害的。
ConcurrentHashMap不同于HashMap中的一点是,concurrentHashMap的put,get,remvoer等方法的实现都是由其内部类Segment实现的,该内部类:
可以看出,该类实现了重入锁保证线程安全,使用final修饰保证方法不被篡改。
3.ConcurrentHashMap 中的 readValueUnderLock
该代码是在值为空的情况才调用;该方法在锁定的情况下获取值。由该方法的注释可以得知,这样做是为了防止在编译器重新定制一个指定的HashEntry实例初始化时,在内存模型中发生意外。
3.ConcurrentHashMa中的put方法:
不允许null的键
可以看出,ConcurrentHashMap和HashMap在对待null键的情况下截然不同,HashMap专门开辟了一块空间用于存储null键的情况,而ConcurrentHashMap则直接抛出空值针异常。
4.ConcurrentHashMa中segment的put方法:
从该方法可以看出,根据key的hash值,计算到table下标位置之后,获取该下标位置的Entry链表,然后从链表第一个位置开始向后遍历,分别比对entry的hash值和key的值,如果都相等且entry不为空,则获取 该entry,设置该entry的value为传入的value,否则往后遍历直到链表中最后一个位置,直到找到相匹配的key和hash;如果e为空,则往该index下插入一个新的entry链表。
该方法使用了重入锁用以保证在同步时候线程的安全。
5.ConcurrentHashMa中segment的rehash方法(当前数组容量不够,进行扩充的操作):
该方法的描述见代码注释
6.ConcurrentHashMap中的remove方法:
7.ConcurrentHashMa中segment的remove方法:
类似于put方法,remove方法也使用了重入锁来保证线程安全;concurrentHashMap的remove方法不同于HashMap的remove方法,在需要删除元素的index下的entry链表没有后续节点时候;后者的remove方法自己会负责回收删除元素的内存并且会移动删除元素后面的元素来覆盖删除元素的位置,concurrentHashMap的remove方法只会回收内存却不会和HashMap一样移动元素。
1.ConcurrentHashMap是一个线程安全的hashMap。相对hashMap多出以下一些特殊属性:
//默认能够同时运行的线程数目 static final int DEFAULT_CONCURRENCY_LEVEL = 16; //最大同时运行的线程数目 static final int MAX_SEGMENTS = 1 << 16; // slightly conservative
2.ConcurrentHashMap的链表实例HashEntry:
static final class HashEntry<K,V> { final K key; final int hash; volatile V value; final HashEntry<K,V> next; HashEntry(K key, int hash, HashEntry<K,V> next, V value) { this.key = key; this.hash = hash; this.next = next; this.value = value; } @SuppressWarnings("unchecked") static final <K,V> HashEntry<K,V>[] newArray(int i) { return new HashEntry[i]; } }
这里需要注意的是Value,value并不是final的,而是一个volatile.
volatile修饰符告诉编译程序不要对该变量所参与的操作进行某些优化。在两种特殊的情况下需要使用volatile修饰符:
第一种情况涉及到内存映射硬件(memory-mapped hardware,如图形适配器,这类设备对计算机来说就好象是内存的一部分一样),
第二种情况涉及到共享内存(shared memory,即被两个以上同时运行的程序所使用的内存)。
大多数计算机拥有一系列寄存器,其存取速度比计算机主存更快。好的编译程序能进行一种被称为“冗余装入和存储的删去”(redundant load and store removal)的优化,即编译程序会在程序中寻找并删去这样两类代码:一类是可以删去的从内存装入数据的指令,因为相应的数据已经被存放在寄存器中;另一种是可以删去的将数据存入内存的指令,因为相应的数据在再次被改变之前可以一直保留在寄存器中。
如果一个指针变量指向普通内存以外的位置,如指向一个外围设备的内存映射端口,那么冗余装入和存储的优化对它来说可能是有害的。
ConcurrentHashMap不同于HashMap中的一点是,concurrentHashMap的put,get,remvoer等方法的实现都是由其内部类Segment实现的,该内部类:
static final class Segment<K,V> extends ReentrantLock implements Serializable {.....}
可以看出,该类实现了重入锁保证线程安全,使用final修饰保证方法不被篡改。
3.ConcurrentHashMap 中的 readValueUnderLock
V readValueUnderLock(HashEntry<K,V> e) { lock(); try { return e.value; } finally { unlock(); } }
该代码是在值为空的情况才调用;该方法在锁定的情况下获取值。由该方法的注释可以得知,这样做是为了防止在编译器重新定制一个指定的HashEntry实例初始化时,在内存模型中发生意外。
/** * Reads value field of an entry under lock. Called if value * field ever appears to be null. This is possible only if a * compiler happens to reorder a HashEntry initialization with * its table assignment, which is legal under memory model * but is not known to ever occur. */
3.ConcurrentHashMa中的put方法:
public V put(K key, V value) { if (value == null) throw new NullPointerException(); int hash = hash(key.hashCode()); return segmentFor(hash).put(key, hash, value, false); }
不允许null的键
可以看出,ConcurrentHashMap和HashMap在对待null键的情况下截然不同,HashMap专门开辟了一块空间用于存储null键的情况,而ConcurrentHashMap则直接抛出空值针异常。
4.ConcurrentHashMa中segment的put方法:
V put(K key, int hash, V value, boolean onlyIfAbsent) { lock(); try { int c = count; if (c++ > threshold) // ensure capacity rehash(); HashEntry<K,V>[] tab = table; int index = hash & (tab.length - 1); HashEntry<K,V> first = tab[index]; HashEntry<K,V> e = first; while (e != null && (e.hash != hash || !key.equals(e.key))) e = e.next; V oldValue; if (e != null) { oldValue = e.value; if (!onlyIfAbsent) e.value = value; } else { oldValue = null; ++modCount; tab[index] = new HashEntry<K,V>(key, hash, first, value); count = c; // write-volatile } return oldValue; } finally { unlock(); }
从该方法可以看出,根据key的hash值,计算到table下标位置之后,获取该下标位置的Entry链表,然后从链表第一个位置开始向后遍历,分别比对entry的hash值和key的值,如果都相等且entry不为空,则获取 该entry,设置该entry的value为传入的value,否则往后遍历直到链表中最后一个位置,直到找到相匹配的key和hash;如果e为空,则往该index下插入一个新的entry链表。
该方法使用了重入锁用以保证在同步时候线程的安全。
5.ConcurrentHashMa中segment的rehash方法(当前数组容量不够,进行扩充的操作):
void rehash() { HashEntry<K,V>[] oldTable = table; int oldCapacity = oldTable.length; //如果数组的长度大于或等于临界值,数组不再进行扩容。 if (oldCapacity >= MAXIMUM_CAPACITY) return; //扩充数组容量为原来大小的两倍。 HashEntry<K,V>[] newTable = HashEntry.newArray(oldCapacity<<1); //重新计算临界值 threshold = (int)(newTable.length * loadFactor); int sizeMask = newTable.length - 1; for (int i = 0; i < oldCapacity ; i++) { // We need to guarantee that any existing reads of old Map can // proceed. So we cannot yet null out each bin. HashEntry<K,V> e = oldTable[i]; if (e != null) { HashEntry<K,V> next = e.next; //获取该链表在数组新的下标 int idx = e.hash & sizeMask; //该链表不存在后续节点,直接把该链表存入新数组,无需其他操作 if (next == null) newTable[idx] = e; else { // 存在后续节点,使用临时变量存储该链表,假设当前节点是最后节点。 HashEntry<K,V> lastRun = e; //获取下标 int lastIdx = idx; //遍历该链表的后续节点 for (HashEntry<K,V> last = next; last != null; last = last.next) { //获取后一个节点的index int k = last.hash & sizeMask; //如果后一个节点的index值和前一个不相同, //则使用后节点的index覆盖前一个节点并且设置该节点为最后节点,依次 //做相同的操作,直到链表的最后一个节点。 if (k != lastIdx) { lastIdx = k; lastRun = last; } } //把链表最后节点的值传递给数组 //该数组下标为最后获取到的下标 newTable[lastIdx] = lastRun; // 遍历老数组下得到的链表的节点值,复制到新的扩容后的数组中。 for (HashEntry<K,V> p = e; p != lastRun; p = p.next) { //计算链表在新数组的下标 int k = p.hash & sizeMask; //获取数组k下标的链表值。 HashEntry<K,V> n = newTable[k]; //把获取到的链表作为需要插入的新的entry的后续节点。 newTable[k] = new HashEntry<K,V>(p.key, p.hash, n, p.value); } } } } //把扩容后的数组返回 table = newTable; }
该方法的描述见代码注释
6.ConcurrentHashMap中的remove方法:
public V remove(Object key) { int hash = hash(key.hashCode()); return segmentFor(hash).remove(key, hash, null); }
7.ConcurrentHashMa中segment的remove方法:
V remove(Object key, int hash, Object value) { lock(); try { int c = count - 1; HashEntry<K,V>[] tab = table; int index = hash & (tab.length - 1); HashEntry<K,V> first = tab[index]; HashEntry<K,V> e = first; while (e != null && (e.hash != hash || !key.equals(e.key))) e = e.next; V oldValue = null; if (e != null) { V v = e.value; if (value == null || value.equals(v)) { oldValue = v; // All entries following removed node can stay // in list, but all preceding ones need to be // cloned. ++modCount; HashEntry<K,V> newFirst = e.next; for (HashEntry<K,V> p = first; p != e; p = p.next) newFirst = new HashEntry<K,V>(p.key, p.hash, newFirst, p.value); tab[index] = newFirst; count = c; // write-volatile } } return oldValue; } finally { unlock(); } }
类似于put方法,remove方法也使用了重入锁来保证线程安全;concurrentHashMap的remove方法不同于HashMap的remove方法,在需要删除元素的index下的entry链表没有后续节点时候;后者的remove方法自己会负责回收删除元素的内存并且会移动删除元素后面的元素来覆盖删除元素的位置,concurrentHashMap的remove方法只会回收内存却不会和HashMap一样移动元素。
发表评论
-
日志记录工具类
2012-11-09 15:51 2026import org.apache.log4j.Log ... -
重入锁
2012-02-08 14:18 1209重入锁(ReentrantLock)是一种递归无阻塞的同步机制 ... -
java需要关注的知识点---并发之加入一个新线程
2012-01-03 11:29 922package com.thread; public ... -
java需要关注的知识点---并发之后台线程
2011-12-30 16:07 948所谓的后台线程,是指在程序运行的时候在后台提供一种通用服务的线 ... -
java需要关注的知识点---并发之从任务中产生返回值
2011-12-29 16:04 746class TaskWithResult implemen ... -
java需要关注的知识点---并发之使用Executor
2011-12-29 16:00 982public class CachedthreadPool ... -
java需要关注的知识点---并发之定义任务
2011-12-29 12:53 8201:定义任务: public class LiftOff ... -
java需要关注的知识点---I0之XML的生成
2011-12-27 17:47 971package com.io; import java. ... -
java需要关注的知识点---I0之对象序列化
2011-12-27 10:59 9831。对象序列化: 序列化是什么: 序列化就是将一个对象的状 ... -
java需要关注的知识点---I0之压缩
2011-12-26 15:38 9371.GZIP压缩: public class GZIPPc ... -
java需要关注的知识点--新I0(NIO)之大文件读取
2011-12-22 14:43 2877在读取大文件的时候,采用管道方式进行分流,使用byteBuff ... -
java需要关注的知识点---Charset
2011-12-21 10:25 8891.Charset 名称必须以字母或数字开头。空字符串不是合法 ... -
java需要关注的知识点---I0之获取特殊属性
2011-12-20 17:51 7571.获取文本的编码方式: String encoding ... -
java需要关注的知识点---I0之新IO(NI0)
2011-12-20 15:40 1205缓冲器操纵数据: ByteBuffer是数据移进移出通道的唯一 ... -
java需要关注的知识点---标准I0流
2011-12-20 11:16 725System.in public class System ... -
java需要关注的知识点---IO流
2011-12-16 17:06 9091.无论何时使用readLine(). ... -
TreeeMap的底层实现
2011-11-28 17:46 1132treeMap插入元素的图解法: 插入前: 插入过程: ... -
java需要关注的知识点---HashSet
2011-11-28 15:20 10671.构造方法: public HashSet() { ... -
java需要关注的知识点---Vector
2011-11-24 17:53 10301.默认初始大小 10. 2.Vector是一个object数 ... -
java需要关注的知识点---LinkedList
2011-11-24 10:19 3281LinkedList是采用双向链表来存储数据: Linked ...
相关推荐
这份"java面试java_interview_guide-master.zip"资源显然是为准备Java面试而设计的,包含了丰富的Java技术知识点和面试常见问题。以下将从Java语言基础、核心特性、集合框架、多线程、网络编程、异常处理、JVM内存...
下面将详细探讨书中涉及的主要知识点。 1. **Java高级特性** - **多线程编程**:Java提供了丰富的API来支持多线程,如`Thread`类、`Runnable`接口和`ExecutorService`。书中可能深入讲解线程同步、死锁和并发容器...
这份"最全的java知识点-面试题目等汇总"涵盖了Java学习和求职面试的关键知识点,包括基础语法、面向对象特性、数据结构与算法、代码规范等多个方面。下面我们将深入探讨这些核心主题。 1. **Java基础**: Java的基础...
本指南旨在帮助求职者掌握Java面试的核心知识点,内容涵盖以下领域: 1. **Java基础** - Java基础知识点 - Java基础进阶 - Java基础深入 2. **集合** - Java集合框架 - 高频面试题解析 - HashMap及其应用 -...
在阅读和学习"【Java面试资料】-JAVA核心面试知识点整理"PDF文档时,应注重理论与实践相结合,通过编写代码加深理解,并关注实际项目中的应用。同时,不断关注Java技术和行业动态,以保持自己的知识体系与时俱进。
总之,ThreadLocal是Java中处理线程安全问题的一种有效手段,尤其适用于需要每个线程都有自己独立副本的场景。然而,理解和正确使用ThreadLocal是至关重要的,避免潜在的内存泄漏和其他并发问题。在实际开发中,根据...
这份面试集锦全面地覆盖了Java开发中的关键知识点,不仅适合准备面试的开发者,也适用于希望巩固和提升自身Java技能的在职工程师。通过深入学习和理解这些内容,将有助于在实际工作中更好地解决问题和优化代码。
"Java多线程-知识点梳理和总结-超详细-面试知识点" Java多线程是Java编程语言中最基本也是最重要的概念之一。多线程编程可以提高程序的执行效率、改善用户体验和提高系统的可扩展性。但是,多线程编程也存在一些...
以下是一些可能出现的重要Java面试知识点: 1. **Java基础**:面试通常会从Java的基础语法开始,如数据类型、变量、运算符、流程控制(if-else,switch-case,for,while,do-while)、数组、字符串处理(String类...
Java私塾面试题----JAVA代码与编程3涵盖了Java编程中的核心知识点,这些是面试官在评估候选人技术能力时经常会问到的问题。以下是一些关键的知识点解析: 1. **基本语法**:Java是一种强类型、面向对象的语言,面试...
"Java-Interview-Advanced-master.zip"这个压缩包显然包含了有关Java高级面试的知识点,旨在帮助开发者准备Java相关的专业面试。这个压缩包可能包含了一系列的代码示例、面试问题、解答以及对Java核心技术的深度解析...
本文将根据“学习android需要的Java知识点列表”中的内容,详细阐述学习Android开发过程中需要掌握的核心Java知识点。 #### 1. Java SDK安装与配置 - **Java SDK**(Software Development Kit)是进行Java程序开发...
本资源"【互联网一线大厂面试+学习指南】 涵盖大部分Java程序员所需要的面试知识点和面试技巧,分享真实面试经历"是一个宝贵的资料库,旨在帮助Java开发者提升自己的技能,成功通过一线大厂的面试。 首先,Java...
以下是对Java相关知识点的详细总结: 1. **基础语法**:Java的基础包括变量、数据类型(基本类型如int、char,引用类型如类、接口)、运算符(算术、比较、逻辑等)、流程控制(条件语句if/else,循环语句for/while...
以上就是Java核心面试知识点整理的核心内容,涵盖了程序员在面试中需要重点掌握的关键概念和知识点,同时这些内容也是Java开发者日常工作中的基础知识。掌握这些知识点,对提升编程能力、优化代码和系统设计都有重要...
以下是对“Java语言编程规范--华为技术有限公司”文档和相关知识点的详细解释。 1. **命名规范** - 类名:使用全大写字母,每个单词首字母大写,如`MyClassName`。 - 变量名和方法名:使用驼峰命名法,首个单词...
Java编程语言是软件开发领域广泛使用的高级编程语言,尤其在企业级应用和...以上就是根据“java第18章java-chapter18.rar”可能涵盖的一些Java编程知识点。学习这些内容有助于提升对Java语言的深入理解和应用能力。
【Java技术资料】-JAVA核心知识点整理 Java是一种广泛使用的高级编程语言,以其跨平台、面向对象、稳定性和高效性而备受青睐。本资料集合涵盖了Java的核心知识点,旨在帮助开发者深入理解和掌握Java语言的关键概念...
针对“深圳-OPPO-Java高级”这个主题,我们可以预想面试会涵盖多个关键知识点,包括但不限于: 1. **Java基础**: - 类与对象:深入理解封装、继承和多态的概念,以及它们在实际编程中的应用。 - 异常处理:了解...
"JAVA核心知识点整理.zip"这个压缩包文件包含了一系列关于Java编程的重要主题,旨在帮助开发者深入理解和掌握Java的核心概念。以下是对这些关键知识点的详细阐述: 1. **Java基础**: - **语法与数据类型**:Java...