有哪些常见的集合?底层结构是什么?有什么区别?
基础
ArrayList和LinkedList有什么区别?ArrayList扩容机制?
ArrayList怎么序列化的知道吗?为什么用transient修饰数组?
快速失败(fail-fast)和安全失败(fail-safe)了解吗?
有哪几种实现ArrayList线程安全的方法?
HashMap相关(重点)
底层数据结构?jdk1.7 和 1.8区别?
数据结构 初始化table和扩容 节点名 节点插入方式 Hash算法 Null的处理
https://blog.****.net/weixin_44141495/article/details/108402128
HashMap的put流程知道吗?HashMap怎么查找元素的呢?
HashMap的哈希/扰动函数是怎么设计的?为什么哈希/扰动函数能降hash碰撞?
为什么HashMap的容量是2的倍数呢?
你还知道哪些哈希函数的构造方法呢?解决哈希冲突有哪些方法呢?
你对红黑树了解多少?为什么不用二叉树/平衡树呢?
红黑树怎么保持平衡的知道吗?旋转 + 染色
为什么HashMap链表转红黑树的阈值为8呢?
扩容在什么时候呢?为什么扩容因子是0.75?
有什么办法能解决HashMap线程不安全的问题呢?
hashmap1.7中的死循环是有多个线程并发扩容形成了环状链表,随后再进行扩容的线程会循环取这个环状链表的节点,造成死循环;其次,环状链表是几个节点相互指向,并不是某个节点自己指向自己。
能具体说一下ConcurrentHashmap的实现吗?
jdk1.7:Segment(ReentrantLock) + HashEntry数组 + 单链表
jdk1.8:Node(CAS + synchronized) + 单链表 / 红黑树
Java7 中 ConcurrentHashMap
使用的分段锁,也就是每一个 Segment 上同时只有一个线程可以操作,每一个 Segment
都是一个类似 HashMap
数组的结构,它可以扩容,它的冲突会转化为链表。但是 Segment
的个数一但初始化就不能改变。
Java8 中的 ConcurrentHashMap
使用的 Synchronized
锁加 CAS 的机制。结构也由 Java7 中的 Segment
数组 + HashEntry
数组 + 链表 进化成了 Node 数组 + 链表 / 红黑树,Node 是类似于一个 HashEntry 的结构。它的冲突再达到一定大小时会转化成红黑树,在冲突小于一定数量时又退回链表。
理解:在 ConcurrentHashMap
中,大部分操作都是通过 CAS 操作来保证原子性的,因为 CAS 操作是一种非常高效的并发控制方式。但是在一些特定的情况下,如扩容或者将链表转换为红黑树时,需要对表头进行修改操作,这时就需要使用 synchronized
来保证对表头修改的原子性和可见性。这种方式在保证了并发安全的前提下,尽可能地减少了对锁的使用,从而提高了并发性能。
有些同学可能对 Synchronized
的性能存在疑问,其实 Synchronized
锁自从引入锁升级策略后,性能不再是问题,有兴趣的同学可以自己了解下 Synchronized
的锁升级。
能具体说一下ConcurrentHashmap的put和get的流程吗(1.7和1.8)?
**jdk1.7: ** 分段锁
put流程
整个流程和HashMap非常类似,只不过是先定位到具体的Segment,然后通过ReentrantLock去操作而已,后面的流程,就和HashMap基本上是一样的。
计算hash,定位到segment,segment如果是空就先初始化
使用ReentrantLock加锁,如果获取锁失败则尝试自旋,自旋超过次数就阻塞获取,保证一定获取锁成功
遍历HashEntry,就是和HashMap一样,数组中key和hash一样就直接替换,不存在就再插入链表,链表同样操作
get流程
get也很简单,key通过hash定位到segment,再遍历链表定位到具体的元素上,需要注意的是value是volatile的,所以get是不需要加锁的。
jdk1.8: CAS + synchronized
put流程
- 首先计算hash,遍历node数组,如果node是空的话,就通过CAS+自旋的方式初始化
- 如果当前数组位置是空则直接通过CAS自旋写入数据
- 写入数据同样判断链表、红黑树,链表写入和HashMap的方式一样,key hash一样就覆盖,反之就尾插法,链表长度超过8就转换成红黑树
get查询
get很简单,和HashMap基本相同,通过key计算位置,table该位置key相同就返回,如果是红黑树按照红黑树获取,否则就遍历链表获取。
为什么Hashtable和ConcurrentHashMap 是不允许键或值为 null 的,HashMap 的键值则都可以为 null?
https://blog.****.net/cy973071263/article/details/126354336
HashMap和HashTable的区别?
底层数据结构 线程安全 初始化数组大小及扩容倍数 是否可以为null
https://blog.****.net/clearLB/article/details/107903603
HashMap和concurrentHashMap的区别?
1.7 1.8 区别
https://blog.****.net/qq_42949615/article/details/124109063?spm=1001.2014.3001.5502
ConcurrentHashMap 和 Hashtable 的区别?
数据结构 初始化和扩容倍数 线程安全的实现方式 (重要!!)
https://javaguide.cn/java/collection/java-collection-questions-02.html#concurrenthashmap-%E5%92%8C-hashtable-%E7%9A%84%E5%8C%BA%E5%88%AB
CopyOnWriteArrayList了解多少?
写时复制:一种优化策略。读写分离,空间换时间:CopyOnWriteArrayList容器允许并发读,读操作是无锁的,性能较高。至于写操作,比如向容器中添加一个元素,则首先将当前容器复制一份,然后在新副本上执行写操作,结束之后再将原容器的引用指向新容器。通过 **锁(ReentrantLock) + 数组拷贝 + volatile ** 保证线程安全。
优点:并发度性能高,适合读多写少的并发环境。
缺点:内存占用大, **其存在数据一致性问题:**CopyOnWrite容器只能保证数据的最终一致性,不能保证数据的实时一致性。如果希望写入的的数据,马上能读到,不要使用CopyOnWrite容器。
讲讲 LinkedHashMap 怎么实现有序的?
讲讲 TreeMap 怎么实现有序的?
Queue下有哪些子类?各自数据结构?
https://blog.****.net/weixin_43895362/article/details/135962789
你能自己设计实现一个HashMap吗?(kuaishou)