收集大量Java经典面试题目📚,内容涵盖了包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 等知识点🏝️。适合准备Java面试的读者参考和复习🌟📢。
❗ ❗ ❗
关注公众号:枫蜜柚子茶 ✅✅
🗳
📑 回 复 “ Java面试 ” 获 取 完 整 资 料⬇ ⬇ ⬇
📖Java并发编程面试Top123道题🔥🔥
1️⃣ 基 础 知 识
2️⃣ 并 发 理 论
3️⃣ 线 程 池
4️⃣ 并 发 容 器 🚩5️⃣ 并 发 队 列
6️⃣ 并 发 工 具 类
并发容器
1. 你经常使用什么并发容器,为什么?
✅ 答:Vector、ConcurrentHashMap、 HashTable。
- ◾ 一般软件开发中容器用的最多的就是HashMap、ArrayList , LinkedList ,等等。
- ◾ 但是在多线程开发中就不能乱用容器,如果使用了未加锁(非同步)的的集合,你的数据就会非常 的混乱。由此在多线程开发中需要使用的容器必须是加锁(同步)的容器。
2. 什么是Vector
Vector与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,访问它 比访问ArrayList慢很多。
( ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。因此,它适合随机查找)
3. ArrayList和Vector有什么不同之处?
◾ Vector方法带上了synchronized关键字,是线程同步的
1️⃣. ArrayList添加方法源码
2️⃣. Vector添加源码(加锁了synchronized关键字)
4. 为什么HashTable是线程安全的?
◾ 因为HasTable的内部方法都被synchronized修饰了,所以是线程安全的。其他的都和HashMap一样
1. HashMap添加方法的源码
2. HashTable添加方法的源码
5. 用过ConcurrentHashMap,讲一下他和HashTable的不同之处?
ConcurrentHashMap是Java5中支持高并发、高吞吐量的线程安全HashMap实现。它由Segment 数组结构和HashEntry数组结构组成。 Segment数组在ConcurrentHashMap里扮演锁的角色,HashEntry则用于存储键-值对数据。一个ConcurrentHashMap里包含一个Segment数组,Segment的结构和HashMap类似,是一种数组和链表结构; 一个Segment里包含一个HashEntry 数组,每个HashEntry是一个链表结构的元素;每个Segment守护着一个HashEntry数组里的元素,当对HashEntry数组的数据进行修改时,必须首先获得它对应的Segment锁。
看不懂???很正常,我也看不懂
💡 总结:
1. HashTable就是实现了HashMap加上了synchronized,而ConcurrentHashMap底层采用分 段的数组+链表实现,线程安全
2. ConcurrentHashMap通过把整个Map分为N个Segment,可以提供相同的线程安全,但是效 率提升N倍,默认提升16倍。
3. 并且读操作不加锁,由于HashEntry的value变量是 volatile的,也能保证读取到最新的值。
4. Hashtable的synchronized是针对整张Hash表的,即每次锁住整张表让线程独占, ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术
5. 扩容:段内扩容(段内元素超过该段对应Entry数组长度的75%触发扩容,不会对整个Map进 行扩容),插入前检测需不需要扩容,有效避免无效扩容
6. Collections.synchronized* 是什么?
📛 注意:* 号代表后面是还有内容的
此方法是干什么的呢,他完完全全的可以把List、 Map、Set接口底下的集合变成线程安全的集合 . Collections.synchronized * :原理是什么,我猜的话是代理模式。
7. Java 中 ConcurrentHashMap 的并发度是什么❓❓
ConcurrentHashMap 把实际 map 划分成若干部分来实现它的可扩展性和线程安全。这种划分是使用并发度获得的,它是 ConcurrentHashMap 类构造函数的一个可选参数,默认值为16,这样在多线程情况下就能避免争用。
在JDK8 后,它摒弃了 Segment(锁段)的概念,而是启用了一种全新的方式实现,利用 CAS 算 法。同时加入了更多的辅助变量来提高并发度,具体内容还是查看源码吧。
8. 什么是并发容器的实现?
何为同步容器:可以简单地理解为通过 synchronized 来实现同步的容器,如果有多个线程调用同步容器的方法,它们将会串行执行。比如 Vector , Hashtable,以及Collections.synchronizedSet ,synchronizedList 等方法返回的容器。可以通过查看 Vector,Hashtable 等这些同步容器的实现代码,可以看到这些容器实现线程安全的方式就是将它们的状 封装起来,并在需要同步的方法上加上关键字 synchronized。
并发容器使用了与同步容器完全不同的加锁策略来提供更高的并发性和伸缩性,例如在ConcurrentHashMap 中采用了一种粒度更细的加锁机制,可以称为分段锁,在这种锁机制下,允许任意数量的读线程并发地访问 map,并且执行读操作的线程和写操作的线程也可以并发的访问map,同时允许一定数量的写操作线程并发地修改 map,所以它可以在并发环境下实现更高的吞吐量。
9. Java 中的同步集合与并发集合有什么区别?
同步集合与并发集合都为多线程和并发提供了合适的线程安全的集合,不过并发集合的可扩展性更高。在 Java1.5 之前程序员们只有同步集合来用且在多线程并发的时候会导致争用,阻碍了系统的扩展性。Java5 介绍了并发集合像ConcurrentHashMap,不仅提供线程安全还用锁分离和内部分区等现代技术提高了可扩展性。
10. SynchronizedMap 和 ConcurrentHashMap 有什么区别?
- ◾ SynchronizedMap 一次锁住整张表来保证线程安全,所以每次只能有一个线程来访为 map。
- ◾ ConcurrentHashMap 使用分段锁来保证在多线程下的性能。
- ◾ ConcurrentHashMap 中则是一次锁住一个桶。 ConcurrentHashMap 默认将hash 表分为 16 个桶,诸如 get,put, remove 等常用操作只锁当前需要用到的桶。
- ◾ 这样,原来只能一个线程进入,现在却能同时有 16 个写线程执行,并发性能的提升是显而易见的。
- ◾ 另外 ConcurrentHashMap 使用了一种不同的迭代方式。在这种迭代方式中,当iterator 被创建后 集合再发生改变就不再是抛出ConcurrentModificationException,取而代之的是在改变时 new 新的数据从而不影响原有的数据, iterator 完成后再将头指针替换为新的数据 ,这样 iterator线程 可以使用原来老的数据,而写线程也可以并发的完成改变。
11. CopyOnWriteArrayList 是什么?
CopyOnWriteArrayList 是一个并发容器。有很多人称它是线程安全的,我认为这句话不严谨,缺少一个前提条件,那就是非复合场景下操作它是线程安全的。
CopyOnWriteArrayList(免锁容器)的好处之一是当多个迭代器同时遍历和修改这个列表时,不会抛 出 ConcurrentModificationException。在CopyOnWriteArrayList 中,写入将导致创建整个底层数组的副本,而源数组将保留在原地,使得复制的数组在被修改时,读取操作可以安全地执行。
12. CopyOnWriteArrayList 的使用场景?
合适📝读多写少的场景。
13. CopyOnWriteArrayList 的缺点?
- ◾ 由于写操作的时候,需要拷贝数组,会消耗内存,如果原数组的内容比较多的情况下,可能导致 young gc 或者 full gc。
- ◾ 不能用于实时读的场景,像拷贝数组、新增元素都需要时间,所以调用一个 set 操作后,读取到数据可能还是旧的,虽然CopyOnWriteArrayList 能做到最终一致性,但是还是没法满足实时性要求。
- ◾ 由于实际使用中可能没法保证 CopyOnWriteArrayList 到底要放置多少数据,万一数据稍微有点多,每次 add/set 都要重新复制数组,这个代价实在太高昂了。在高性能的互联网应用中,这种操作分分钟引起故障。
14. CopyOnWriteArrayList 的设计思想?
- ◾ 读写分离,读和写分开
- ◾ 最终一致性
- ◾ 使用另外开辟空间的思路,来解决并发冲突