携程旅游事业部后端暑期实习一面面经
《面试题目》
- CountdownLatch为什么配合线程池使用,为什么不能过来一个任务new一个thread?
- 线程池如何设置(参数配置策略)?
- 虚拟线程十万量级下为什么还要用线程池?
- MCP(Model Context Protocol)怎么设计的?
- 微服务场景下怎么根据下游表现动态修改线程池?
- 怎么监控线程池,从哪些维度切入,有用过对应工具吗?
- 讲一下Java的锁机制。
- 分布式锁怎么做,除了Redis NX锁还有哪些方案?
- 热Key问题怎么解决?
- Java哪个版本引入了虚拟线程,Spring哪个版本支持SSE(Server-Sent Events)?
- ThreadLocal会遇到哪些问题(内存泄漏、线程复用等)?
- ThreadLocal里的信息是怎么传递下去的?
- 线上Full GC怎么去排查?
- 新生代向老年代转换有哪几种情况?
《参考解析》
- 线程池与虚拟线程:线程池主要用于复用线程,减少线程创建销毁开销;new thread在请求量大时会导致系统OOM或CPU频繁切换。虚拟线程虽然轻量,但仍需通过调度器管理,且在某些资源受限场景下,线程池依然能提供必要的限流与隔离作用。
- 分布式锁方案:除Redis NX,还有Zookeeper(基于临时有序节点)、基于数据库的乐观锁/悲观锁,以及基于Etcd的实现。
- 热Key问题:通常采用本地缓存(Guava/Caffeine)、Redis集群分片、或将Key分散到多个副本中进行读取以降低单个热点节点的负载。
- Full GC排查:通过jstat、jmap导出堆快照,利用MAT分析内存泄漏。关注老年代空间是否紧张、元空间溢出、或者System.gc()调用等因素。
- 新生代晋升老年代:包括对象年龄超过MaxTenuringThreshold、大对象直接进入老年代、Survivor区空间不足时的动态对象年龄判断等。