Java 高级面试问题及答案
问题1:请解释Java内存模型(JMM)及其重要性。
答案:
Java内存模型(JMM)是一个抽象的概念,它定义了Java程序中各种变量(线程共享变量)的访问规则,以及在并发环境下,这些变量如何通过主内存和工作内存进行交互。JMM的主要目的是解决多线程程序中的可见性、原子性和有序性问题。
- 可见性:确保一个线程对共享变量的修改能够及时地被其他线程观察到。
volatile
关键字可以确保变量的修改对所有线程都是可见的。 - 原子性:保证一个操作或者一系列操作在并发环境中,要么全部执行,要么全部不执行。可以通过
synchronized
和java.util.concurrent
包中的原子类来实现。 - 有序性:在单线程环境中,代码的执行顺序是按照编写的顺序执行的,但在多线程环境中,由于编译器优化和处理器优化,指令重排序可能导致执行顺序与编写顺序不同。
synchronized
和volatile
可以禁止指令重排序。
JMM的重要性在于它为编写正确且高效的并发程序提供了理论基础。
问题2:什么是Java中的双亲委派模型?它有什么优点?
答案:
Java中的双亲委派模型是一种类加载机制,它的核心思想是:每个类加载器在加载一个类时,首先会委托给它的父类加载器去尝试加载这个类,只有当父类加载器无法完成这个请求时,子类加载器才会尝试自己去加载。
优点:
- 避免重复加载:确保一个类只被加载一次,无论这个类被请求加载多少次。
- 安全:可以防止核心库的类被篡改。因为自定义类加载器无法加载
java.*
包下的类,这样就保证了Java核心库的安全性。 - 层次性:类加载器的层次结构允许Java应用分层,上层可以覆盖下层的实现,提供了更大的灵活性。
问题3:解释一下Java中的强引用、软引用、弱引用和虚引用的区别。
答案:
Java中的引用类型可以分为以下几类:
- 强引用(Strong Reference):如果一个对象具有强引用,那么垃圾回收器永远不会回收这个对象,直到JVM耗尽所有可用内存。
- 软引用(Soft Reference):如果一个对象只具有软引用,那么在内存不足时,垃圾回收器会回收这些对象以释放内存,可以通过
java.lang.ref.SoftReference
实现。 - 弱引用(Weak Reference):弱引用不足以阻止对象的垃圾回收,无论内存是否足够,只要没有其他强引用指向该对象,垃圾回收器就会回收它,可以通过
java.lang.ref.WeakReference
实现。 - 虚引用(Phantom Reference):一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来获取一个对象的实例。其主要作用是在对象被回收时收到一个系统通知,可以通过
java.lang.ref.PhantomReference
实现。
问题4:请解释Java中的锁优化策略有哪些?
答案:
Java虚拟机对锁进行了多种优化,以减少锁操作的开销,提高性能。以下是一些常见的锁优化策略:
- 锁粗化(Lock Coarsening):将多个连续的细粒度锁合并为一个粗粒度的锁,减少锁的开销。
- 锁消除(Lock Elimination):在编译期间,如果确定某个锁不会引发线程安全问题,编译器会消除这个锁。
- 轻量级锁(Lightweight Locking):在没有多线程竞争的情况下,使用CAS操作代替重量级锁,减少操作系统的调用开销。
- 偏向锁(Biased Locking):如果一个对象的锁总是由同一个线程获取,那么这个锁会偏向这个线程,减少锁的竞争。
- 自旋锁(Spinlock):在线程竞争不激烈的情况下,让线程执行忙循环(自旋)一段时间,而不是立即阻塞线程,提高响应速度。
- 适应性自旋(Adaptive Spinning):自旋的时间不再固定,而是根据线程的历史自旋次数和锁的竞争情况动态调整。
以上是Java中常见的锁优化策略,它们可以在不同的场景下提高程序的并发性能。