1.判断一个集合类是否为线程安全的机制是什么?
怎么判断一个Java类是否是线程安全?有那些角度?_不积跬步,无以致千里的博客-CSDN博客_java怎么判断线程是否安全
2.说一下 Fail-Fast 机制,结合源码 说一下(如果可以的话)
3.Java中有哪些容器(集合类)?
Java中的集合类主要由Collection和Map这两个接口派生而出,其中Collection接口又派生出三个子接口,分别是Set、List、Queue。所有的Java集合类,都是Set、List、Queue、Map这四个接口的实现类,这四个接口将集合分成了四大类,其中
-
Set代表无序的,元素不可重复的集合;
-
List代表有序的,元素可以重复的集合;
-
Queue代表先进先出(FIFO)的队列;
-
Map代表具有映射关系(key-value)的集合。
这些接口拥有众多的实现类,其中最常用的实现类有HashSet、TreeSet、ArrayList、LinkedList、ArrayDeque、HashMap、TreeMap等。
4.Java中的容器,线程安全和线程不安全的分别有哪些?
java.util包下的集合类大部分都是线程不安全的,例如我们常用的HashSet、TreeSet、ArrayList、LinkedList、ArrayDeque、HashMap、TreeMap,这些都是线程不安全的集合类,但是它们的优点是性能好。如果需要使用线程安全的集合类,则可以使用Collections工具类提供的synchronizedXxx()方法,将这些集合类包装成线程安全的集合类。
java.util包下也有线程安全的集合类,例如Vector、Hashtable。这些集合类都是比较古老的API,虽然实现了线程安全,但是性能很差。所以即便是需要使用线程安全的集合类,也建议将线程不安全的集合类包装成线程安全集合类的方式,而不是直接使用这些古老的API。
从Java5开始,Java在java.util.concurrent包下提供了大量支持高效并发访问的集合类,它们既能包装良好的访问性能,有能包装线程安全。这些集合类可以分为两部分,它们的特征如下:
-
以Concurrent开头的集合类:
以Concurrent开头的集合类代表了支持并发访问的集合,它们可以支持多个线程并发写入访问,这些写入线程的所有操作都是线程安全的,但读取操作不必锁定。以Concurrent开头的集合类采用了更复杂的算法来保证永远不会锁住整个集合,因此在并发写入时有较好的性能。
-
以CopyOnWrite开头的集合类:
以CopyOnWrite开头的集合类采用复制底层数组的方式来实现写操作。当线程对此类集合执行读取操作时,线程将会直接读取集合本身,无须加锁与阻塞。当线程对此类集合执行写入操作时,集合会在底层复制一份新的数组,接下来对新的数组执行写入操作。由于对集合的写入操作都是对数组的副本执行操作,因此它是线程安全的。
Java:CAS(乐观锁) - 简书 (jianshu.com)
什么是CAS机制?如何解决ABA问题?_小问号阿的博客-CSDN博客
ReentrantLock详解_SunStaday的博客-CSDN博客_reentrantlock
JAVA Semaphore详解 - 简单爱_wxg - 博客园 (cnblogs.com)
ArrayList
相关阅读:
ArrayList源码分析(扩容机制jdk8) - 掘金 (juejin.cn)
1.ArrayList 初始化时数组的默认长度是多少?
默认长度为10。但是ArrayList的默认长度是有jdk版本差异的,在jdk8版本之前默认长度是10。而在jdk8版本的时候对ArrayList数组的默认长度进行了优化,将原来的默认长度10,改为了初始长度为0。当我们在首次添加元素,需要分配数组空间时,jdk自动帮我们进行了扩容操作,将初始数组长度扩容成了10。这样做有效地降低了无用内存的占用!它利用了数组扩容的特性来完成集合的这些功能,这也就是ArrayList集合查询快、增删慢的原因了!
2.ArrayList 扩容是扩容多少倍?扩容后是用原来的数组还是新的数组?
新的容量是旧容量加上旧容量值右移一位得到的,一个数右移n(n>0)位的结果等于这个数除以2^n的整数部分;新数组。
3.ArrayList 是一个线程安全的集合类吗?
不是。
4.ArrayList 和 LinkedList 的使用场景
(1)如果应用程序对数据有较多的随机访问,ArrayList对象要优于LinkedList对象;
( 2 ) 如果应用程序有更多的插入或者删除操作,较少的随机访问,LinkedList对象要优于ArrayList对象;
(3)不过ArrayList的插入,删除操作也不一定比LinkedList慢,如果在List靠近末尾的地方插入,那么ArrayList只需要移动较少的数据,而LinkedList则需要一直查找到列表尾部,反而耗费较多时间,这时ArrayList就比LinkedList要快。
5.谈谈CopyOnWriteArrayList的原理?
Java CopyOnWriteArrayList详解 - 简书 (jianshu.com)
LinkedList
相关阅读:
Java如何实现LinkedList按索引下标进行插入 - 枫叶像思念 - 博客园 (cnblogs.com)
HashMap
1.HashMap实现原理?
HashMap的实现原理_〆、风神的博客-CSDN博客_hashmap底层实现原理
2.如何得到一个线程安全的Map?
-
使用Collections工具类,将线程不安全的Map包装成线程安全的Map;
-
使用java.util.concurrent包下的Map,如ConcurrentHashMap;
-
不建议使用Hashtable,虽然Hashtable是线程安全的,但是性能较差。
3.介绍一下HashMap的扩容机制?
Hashmap实现原理及扩容机制详解_lkforce的博客-CSDN博客_hashmap扩容机制
4.说一说HashMap和HashTable的区别
HashMap和Hashtable的区别_xuhuaabc的博客-CSDN博客_hashmap和hashtable
5.hashmap为什么线程不安全?
首先HashMap是线程不安全的,其主要体现:
#1.在jdk1.7中,在多线程环境下,扩容时会造成环形链或数据丢失。
#2.在jdk1.8中,在多线程环境下,会发生数据覆盖的情况。
面试官:HashMap 为什么线程不安全? - 腾讯云开发者社区-腾讯云 (tencent.com)
6.介绍一下ConcurrentHashMap是怎么实现的?
1.7
漫画:什么是ConcurrentHashMap? - 知乎 (zhihu.com)
ConcurrentHashMap(JDK8) - 腾讯云开发者社区-腾讯云 (tencent.com)
7.说一说HashSet的底层结构?
HashSet是基于HashMap实现的,默认构造函数是构建一个初始容量为16,负载因子为0.75 的HashMap。它封装了一个 HashMap 对象来存储所有的集合元素,所有放入 HashSet 中的集合元素实际上由 HashMap 的 key 来保存,而 HashMap 的 value 则存储了一个 PRESENT,它是一个静态的 Object 对象。