[7]-集合类
来源:互联网 发布:云之家mac版本 编辑:程序博客网 时间:2024/05/07 23:02
HashMap(容量,负载因子):非线程安全
- 数组+链表实现
当Entry节点数量超过容量负载因子,进行扩容*2,进行resize()
对key的hashCode()进行indexfor获得位置,因为取余效率低
- 如果该位置没有碰撞、直接存到bucket中;如果发生碰撞,遍历链表有没有相等的key,
- 有就替换该Entry的value;没有就addEntry(),是否扩容,创建一个Entry作为链表头
- jdk8后来做的改进是、如果碰撞导致链表过长,长度超过8,把链表转换成红黑树
- resize()就是线程不安全的源头:多线程同时resize()可能会产生Entry的环
Entry put(K key,v value){ if (key == null) { return putForNullKey(value); } int i = indexFor(hash(key), table.length); for (Entry< K,V> e = table[i]; e != null; e = e.next) { if (e.hash == hash && (eKey== key || key.equals(eKey))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }void addEntry(int hash, K key, V value, int bucketIndex) { if ((size >= threshold) && (null != table[bucketIndex])) { resize(2 * table.length); hash = (null != key) ? hash(key) : 0; bucketIndex = indexFor(hash, table.length); } createEntry(hash, key, value, bucketIndex);}void createEntry(int hash, K key, V value, int bucketIndex) { Entry<K,V> e = table[bucketIndex]; table[bucketIndex] = new Entry<>(hash, key, value, e); size++;}void transfer(Entry[] newTable){ Entry[] src = table; int newCapacity = newTable.length; for (int j = 0; j < src.length; j++) { Entry< K,V> e = src[j]; if (e != null) { src[j] = null; do { Entry<K,V> next = e.next; int i = indexFor(e.hash, newCapacity); e.next = newTable[i]; newTable[i] = e; e = next; } while (e != null); } }}
Hashtable:所有函数都是同步有锁
- 效率低下、所有访问HashTable的线程都必须
竞争同一把锁
- 继承`Dictionary类,实现了Map接口
- 他的key、value都不能是null
ConcurrentHashMap:锁分段、元素HashMap
- 由Segment[]数组构成、每一个Segment与HashMap类型相似
- Entry的变量final类型(除了value:volatile)
- 除了容量、负载因子,还加了一个参数
concurrencyLevel
egment[]数组的长度是大于或等于concurrencyLevel的最小的2的N次方值
同步有锁、
锁分段
技术、- 首先将数据分成一段一段的存储,然后给每一段数据配一把锁,
- 当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问
定位Segment:HashMap中的hash()一样,为了减少哈希冲突
- Segment< K,V> segmentFor(hash)右移28位、让高四位参与到运算中)&(segmentMask掩码默认是8)
- get()是无锁的:判断entry的value是否为null,是就加锁
public V get(Object key) { int hash = hash(key); return segmentFor(hash).get(key, hash); } V get(Object key, int hash) { //volatile修饰count if (count != 0){ HashEntry<K,V> e = getFirst(hash); while (e != null) { if (e.hash == hash && key.equals(e.key)) { V v = e.value; if (v != null) { return v; } return readValueUnderLock(e); } e = e.next; } } return null;}
- put()、remove()、ReentrantLock加锁
- 修改:突然另一个进程修改了我们想get()的Entry的value:value是volatile的,没关系
- 增加:突然另一个线程在链表头put()了一个我们想get()的Entry
- if (v != null) 的判断,对new出来的对象进行状态检测,不为null,返回
- 还为null的话,readValueUnderLock(),锁定之后返回一个值(value不允许为null)
- 删除:突然另一个进程删除了我们想get()的Entry
- 因为next变量是final的,所以只能在table[index]重链接一条单链表,e1-e2-e3-e4,删e3
- 变成e2-e1-e4,如果我们已顺着原链表到了e1了,继续顺着原来的走,仍会返回e3
- ConcurrentHashMap的迭代器不是快速失败
List
- ArrayList:动态扩容1.5倍(下标访问-尾部插入高效-其他位置System.arraycopy())
- LinkedList:双向链表(两头插入删除高效-其他位置)
- CopyOnWriteArrayList(java.util.concurrent):只有写锁、没有读锁。适合读多写少的场景
- 在修改时先复制一个快照Arrays.copyof(),每次写都在新数组写,指针指向新数组
Map
- LinkedHashMap:双向链表:按Entry插入顺序排序:LRU(accessOrder=true)
- TreeMap:红黑树实现、iterator()有序遍历key、Comparable或Comparator
Queue:两端出入的List
- PriorityQueue:二叉堆:iterator()不保证有序遍历
- LinkedList:双向链表:唯一允许放入null的Queue
- ArrayDeque:循环数组:push尾增,pop头增,尾追上头无空间
- ConcurrentLinkedQueue:线程安全:单向链表:CAS无锁
- PriorityBlockingQueue:线程安全:二叉堆:读写一把锁:阻塞接口,无阻塞特性
- ArrayBlockingQueue:线程安全阻塞:循环数组:读写一把锁
- LinkedBlockingQueue:线程安全阻塞:链表:两把锁
public class LruLinkedHashMap<K,V> extends LinkedHashMap<K,V>{ public int cap; LruLinkedHashMap(int cap){ //LinkedHashMap(int initialCapacity,float loadFactor,boolean accessOrder) super(cap,0.75f,true); this.cap=cap; } public boolean removeEldestEntry(Map.Entry<K, V> eldest){ return size()>cap; }}
0 0
- [7]-集合类
- Map集合(集合类)
- 集合类 Map集合
- java-集合类-(7)总结
- 集合和泛型7-----集合5 强类型集合基类
- 集合类 List集合 / LinkedList集合
- 7、集合
- 集合类
- 集合类
- 集合类
- 集合类
- 集合类
- 集合类
- 集合类...
- 集合类
- 集合类
- 集合类:
- 集合类
- JSPatch中的CGSize和其他注意点
- hadoop2.0的datanode多存储硬盘设置数据副本存放策略
- HTML标签属性大全(开发人员必备)
- 【Spring学习笔记】Spring中Application Context和Servlet Context的区别
- 电力行业的行政区划及主要生产系统
- [7]-集合类
- activity dialog 透明背景以及是否外部点击可以取消dialog
- ecshop后台添加一个完整的统计用户信息的功能
- 通过shell命令提取文件内容(C实现)
- openSession和getCurrentSession
- 有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个数列的前20项之和。
- android studio 一次编译错误:Error:Minimum supported Gradle version is 2.14.1.
- 欢迎使用CSDN-markdown编辑器
- Android 跑马灯效果的实现