Java中级面试是技术人职业发展的重要分水岭。与初级面试不同,中级面试官更关注候选人对技术原理的掌握深度和实际应用能力。根据我参与过的200+场技术面试经验,80%的候选人会在集合框架、并发编程和JVM调优这三个核心领域暴露出知识盲区。
这份精讲内容源自真实的中高级Java岗位面试题库,覆盖了字节跳动、阿里P6/P7级别岗位的常考知识点。不同于市面上简单的QA汇总,我们将采用"原理剖析->场景分析->实战演示"的三段式讲解法,确保每个知识点都能真正内化为你的技术储备。
JDK8的HashMap实现中有个关键细节:当链表长度超过8时会转为红黑树。但为什么阈值是8?通过阅读源码可以发现:
java复制static final int TREEIFY_THRESHOLD = 8;
// 基于泊松分布的计算结果
// 当hashCode离散良好时,链表长度达到8的概率不足千万分之一
实际开发中遇到过的一个典型案例:使用自定义对象作为Key时未重写hashCode(),导致HashMap退化为链表。解决方案是:
踩坑提醒:JDK7的HashMap在多线程扩容时可能形成环形链表,导致CPU100%。这是ConcurrentHashMap被广泛使用的重要原因之一。
对比不同JDK版本的实现差异:
实测数据显示,在16核服务器上JDK8版本的并发写性能比JDK7提升近3倍。关键改进点在于:
AbstractQueuedSynchronizer是Java并发包的核心基础,其设计中有几个精妙之处:
以CountDownLatch为例,其await()方法实际上调用了AQS的acquireSharedInterruptibly()。在电商系统秒杀场景中,我们可以这样使用:
java复制// 商品库存预热
CountDownLatch latch = new CountDownLatch(3);
executor.execute(() -> {
cacheService.warmUp();
latch.countDown();
});
// ...其他预热任务
latch.await(5, TimeUnit.SECONDS); // 关键超时控制
ThreadLocal的经典内存泄漏场景:
解决方案对比:
通过实际案例展示如何分析GC日志:
code复制[GC (Allocation Failure)
[PSYoungGen: 153600K->25568K(179200K)]
153600K->25568K(588800K),
0.0289709 secs]
关键指标解读:
调优经验:
线上环境排查内存泄漏的标准流程:
曾处理过的一个典型案例:某订单系统每隔3天就会OOM。最终发现是第三方SDK缓存了XML解析结果,通过WeakHashMap改造解决。
Spring三级缓存解决循环依赖的完整流程:
关键限制:
测试环境:MacBook Pro i7, JDK11
| 代理类型 | 创建耗时(ms) | 调用耗时(ns) |
|---|---|---|
| JDK动态代理 | 125 | 342 |
| CGLIB | 210 | 158 |
| ByteBuddy | 95 | 121 |
实战建议:
HikariCP之所以快的关键设计:
配置建议:
properties复制# 连接数 = ((核心数 * 2) + 有效磁盘数)
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.connection-timeout=3000
# 防止网络分区导致连接泄漏
spring.datasource.hikari.leak-detection-threshold=60000
生产环境慢查询优化案例:
三种实现方式的可靠性对比:
Redisson实现分布式锁的最佳实践:
java复制RLock lock = redisson.getLock("orderLock");
try {
// 尝试加锁,最多等待100秒,上锁后30秒自动解锁
if (lock.tryLock(100, 30, TimeUnit.SECONDS)) {
// 处理业务逻辑
}
} finally {
lock.unlock();
}
常见幂等解决方案:
支付系统的典型实现:
java复制@Idempotent(key = "#paymentRequest.tradeNo",
expire = 24,
unit = TimeUnit.HOURS)
public PaymentResult process(PaymentRequest request) {
// 业务处理
}
JMH使用中的常见误区:
正确的基准测试示例:
java复制@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
public class JsonBenchmark {
private ObjectMapper mapper = new ObjectMapper();
@Benchmark
public void testJackson(Blackhole bh) {
bh.consume(mapper.writeValueAsString(data));
}
}
缓存策略选择的决策树:
缓存击穿防护方案对比:
Spring环境中策略模式的最佳实践:
java复制@Service
public class PaymentService {
@Autowired
private Map<String, PaymentStrategy> strategies;
public void process(String type, PaymentContext context) {
strategies.get(type).execute(context);
}
}
// 每个策略实现类添加@Component("alipay")等注解
Spring事件机制的实际应用:
java复制// 定义事件
public class OrderCreatedEvent extends ApplicationEvent {
public OrderCreatedEvent(Order source) {
super(source);
}
}
// 发布事件
applicationContext.publishEvent(new OrderCreatedEvent(order));
// 监听处理
@EventListener
public void handleEvent(OrderCreatedEvent event) {
// 发送通知等操作
}
常见的反模式:
推荐做法:
日志优化的关键点:
日志配置示例:
xml复制<AsyncLogger name="com.example" level="INFO">
<AppenderRef ref="FILE"/>
<!-- 避免同步日志阻塞业务线程 -->
<AppenderRef ref="ASYNC_CONSOLE"/>
</AsyncLogger>
在技术面试中,面试官往往会通过追问"为什么"来考察候选人的理解深度。比如当被问到HashMap的工作原理时,可以主动延伸讨论:为什么选择数组+链表/红黑树的结构?负载因子0.75的数学依据是什么?这样的回答方式能展现真正的技术功底。