Java多线程是Java开发中的核心技能之一,尤其在面试中,对于一线大厂的面试者来说,深入理解和掌握多线程的相关知识点至关重要。以下是一些关键的Java多线程面试知识点:
1. **自旋锁**:自旋锁是一种等待机制,当锁被占用时,尝试获取锁的线程不会立即阻塞,而是会循环检查锁是否可用。自旋锁可能导致的问题包括资源浪费(线程不断检查锁状态,消耗CPU资源)和死锁(如果多个线程都在自旋,可能会导致大家都无法获取到锁)。使用自旋锁需要注意避免无限制地自旋,以及在适当的时候转换为阻塞状态。
2. **线程锁状态**:Java中的锁主要有两种状态:无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态。这些状态可以通过对象头中的标志位来标记。例如,`synchronized`关键字实现的锁就是重量级锁。
3. **Java对象内存布局**:在HotSpot VM中,一个Java对象通常包含三部分:对象头(包括Mark Word和Class Pointer)、实例数据和填充数据。Mark Word用于存储锁状态和其他元信息。
4. **锁的性能优化**:JVM对锁进行了多种优化,如锁消除、锁粗化、轻量级锁、偏向锁和自旋锁等。这些优化旨在减少锁带来的开销,提高并发性能。
5. **独享锁/共享锁**:在Java中,独享锁(互斥锁)通常指`synchronized`,只允许一个线程访问;共享锁(读锁)如`ReadWriteLock`的读锁,允许多个线程同时读取,但写操作是独占的。
6. **ReentrantLock**:它是可重入锁,允许同一线程多次获取锁。其底层基于AQS(AbstractQueuedSynchronizer),加锁和解锁涉及到CAS操作和节点的插入与移除。
7. **ReentrantReadWriteLock与StampedLock**:两者都是可重入的,但StampedLock提供更细粒度的锁,支持乐观读锁和写锁,比ReentrantReadWriteLock性能更高。在读多写少的场景下,StampedLock更优。
8. **阻塞队列**:如`LinkedBlockingQueue`和`ArrayBlockingQueue`,前者基于链表结构,后者基于数组。它们都使用内部锁机制来保证线程安全,但实现方式不同,例如ArrayBlockingQueue使用的是公平锁。
9. **HashMap数据结构**:在JDK1.7中,HashMap使用数组+链表实现,而在JDK1.8中引入了红黑树,使得查找、插入和删除操作的平均时间复杂度降低。
10. **HashMap扩容**:当哈希表负载因子(元素数量/容量)达到阈值时触发扩容,扩容通常是原容量的两倍,这样保证哈希冲突的概率较低,且扩容后的旧链表可以平滑迁移到新数组中。
11. **哈希冲突解决**:常见的哈希冲突解决方法有开放寻址法、链地址法、再哈希法等。HashMap采用链地址法,将哈希冲突的元素链接在一起。
12. **HashMap的容量和加载因子**:初始容量影响哈希表的大小,加载因子则决定了何时进行扩容。合理的设置可以平衡空间利用率和查找效率。
13. **HashMap为什么不直接使用红黑树**:因为哈希表在大多数情况下负载因子并不高,链表足以处理冲突。只有在冲突严重时才转换为红黑树,以提高性能。
14. **线程池的工作队列**:线程池的工作队列分为无界队列(如`LinkedBlockingQueue`)和有界队列(如`ArrayBlockingQueue`)。无界队列可能导致任务堆积,有界队列能限制并发任务的数量,防止资源耗尽。
15. **指令重排**:为了优化执行效率,编译器和处理器可能会对指令进行重新排序。这种现象在多线程环境下可能引发问题,如可见性问题。
16. **Happen-Before原则**:这是JMM(Java内存模型)的一部分,定义了线程间的可见性和有序性。遵循这些原则可以确保并发程序的正确性。
17. **volatile防止指令重排**:volatile关键字可以阻止其修饰的变量在不同线程间发生指令重排,确保对其他线程的可见性。
18. **ThreadLocal解决Hash冲突**:ThreadLocal不是解决哈希冲突的工具,而是每个线程拥有独立的副本,避免了线程间的共享数据冲突。
19. **ThreadLocalMap的键是弱引用**:ThreadLocalMap的键使用弱引用,当没有其他引用指向ThreadLocal实例时,垃圾收集器可以回收ThreadLocal,从而避免内存泄漏。
20. **防止ThreadLocal内存泄漏**:及时清理不再使用的ThreadLocal实例,或者在线程结束时清理ThreadLocalMap,防止引用循环导致内存泄漏。
掌握这些知识点并结合源码分析、性能优化和实际应用,能够显著提高面试者在一线大厂Java多线程面试中的竞争力,有助于提升职业发展。建议学习者按照课程大纲的顺序,结合实践深入理解,避免仅仅死记硬背题目。