面试现场:大厂Java岗的“灵魂拷问”
面试官(推了推眼镜):欢迎来我们公司面试,先简单自我介绍一下吧。
谢飞机(挠头):我叫谢飞机,三年Java开发经验,会写for循环,能跑通Hello World,熟练使用Ctrl+C和Ctrl+V……
面试官(皱眉):咳咳,咱们进入正题。第一轮问题,关于Java核心和多线程。
第一轮:基础不牢,地动山摇
-
面试官:说说你对Java线程池的理解,为什么不用
new Thread?谢飞机:啊?线程池?那不是池塘养鱼吗?我们项目都是
new Thread(),感觉挺快的,就是服务器经常炸……但重启一下就好了!面试官(扶额):……那你至少知道
Runnable和Thread的区别吧?谢飞机:哦!这个我会!
Runnable是接口,Thread是类,就像爸爸和儿子的关系!面试官(勉强点头):嗯……勉强算对一半。
-
面试官:那你说说
ExecutorService常用的实现类有哪些?谢飞机:有
FixedThreadPool、CachedThreadPool,还有那个……SingleThreadExecutor!我背过!面试官(略带欣慰):不错,那这些线程池的核心参数你知道吗?比如核心线程数、最大线程数?
谢飞机:核心线程数就是核心的,最大线程数就是最大的……(陷入沉思)具体咋配?我们都是默认的!
面试官:……行吧。
-
面试官:如果任务很多,线程池怎么处理?
谢飞机:加机器呗!不行就堆
new Thread,人多力量大!面试官(叹气):这是在拼资源,不是在写代码……
第二轮:JUC与并发进阶
面试官:接下来聊聊ConcurrentHashMap,它和HashMap有什么区别?
谢飞机:哦!这个我知道!HashMap不能多线程用,会死锁!我们组长说的!
面试官:准确说是可能扩容时形成环链导致死循环,JDK8之后改用红黑树和CAS+synchronized优化了。
谢飞机:对对对!就是那个……红什么树!我们没遇到过,因为我们不用HashMap做并发。
面试官:那你们用什么?
谢飞机:用new HashMap()加synchronized块!
面试官:……那你了解ReentrantLock和synchronized的区别吗?
谢飞机:synchronized是关键字,ReentrantLock是类,可以lock()和unlock(),还能尝试锁!我看过源码……注释!
面试官(点头):还行。那CountDownLatch和CyclicBarrier呢?
谢飞机:都是等人的!一个是一次性门禁,一个是循环打卡机!
面试官(居然笑了):比喻得……还挺形象。
第三轮:Spring全家桶与中间件
面试官:Spring中Bean的作用域有哪些?
谢飞机:singleton、prototype,还有request、session!
面试官:很好。那Bean的生命周期?
谢飞机:出生、长大、工作、死亡……哦不对,是实例化、填充、初始化、销毁!
面试官:那@Autowired和@Resource有什么区别?
谢飞机:@Autowired按类型,@Resource按名字!名字优先!
面试官(满意):不错。那Redis持久化机制?
谢飞机:RDB是拍快照,AOF是记日记!我们线上只开RDB,怕AOF太大!
面试官:MySQL索引失效场景?
谢飞机:like左边有%、函数操作字段、类型转换……我背过八股文!
面试官(微笑):今天就到这里,你的基础还算扎实,虽然有些地方需要加强。回去等通知吧。
谢飞机(激动):好嘞!我回去就把new Thread全换成线程池!
参考答案详解
1. Java线程池核心参数
线程池核心参数由ThreadPoolExecutor构造函数定义:
public ThreadPoolExecutor(
int corePoolSize, // 核心线程数,常驻线程
int maximumPoolSize, // 最大线程数,临时扩容上限
long keepAliveTime, // 非核心线程空闲存活时间
TimeUnit unit,
BlockingQueue<Runnable> workQueue, // 任务队列
ThreadFactory threadFactory, // 线程工厂
RejectedExecutionHandler handler // 拒绝策略
)
- corePoolSize:核心线程即使空闲也不会被回收(除非设置
allowCoreThreadTimeOut) - maximumPoolSize:最大线程上限
- workQueue:常见有
ArrayBlockingQueue(有界)、LinkedBlockingQueue(无界)、SynchronousQueue(直接传递) - 拒绝策略:
AbortPolicy(抛异常)、CallerRunsPolicy(调用者线程执行)等
使用线程池优势:避免频繁创建销毁线程、控制并发数、提高资源利用率。
2. ConcurrentHashMap vs HashMap
| 对比项 | HashMap | ConcurrentHashMap | |--------|--------|------------------| | 线程安全 | 否 | 是 | | 实现方式 | JDK7:分段锁;JDK8:CAS + synchronized + 红黑树 | | 扩容机制 | 单线程rehash | 多线程协助迁移(transfer) | | 迭代器 | fail-fast | fail-safe |
3. ReentrantLock vs synchronized
synchronized:JVM层面,自动释放,不可中断,非公平ReentrantLock:API层面,需手动unlock(),支持中断、超时、公平锁
4. CountDownLatch vs CyclicBarrier
CountDownLatch:计数器减到0后触发,一次性,适用于等待多个任务完成CyclicBarrier:计数器加到阈值后触发,可重用,适用于多线程同步到达某点
5. Spring Bean生命周期
- 实例化(Instantiation)
- 属性赋值(Populate)
- 初始化前(BeanPostProcessor#postProcessBeforeInitialization)
- 初始化(InitializingBean#afterPropertiesSet 或 @PostConstruct)
- 初始化后(BeanPostProcessor#postProcessAfterInitialization)
- 使用
- 销毁(DisposableBean#destroy 或 @PreDestroy)
6. Redis持久化
- RDB:定时快照,恢复快,可能丢失数据
- AOF:记录每条写命令,数据更安全,文件大,恢复慢
- 建议:生产环境同时开启,RDB用于备份,AOF用于灾难恢复
7. MySQL索引失效场景
LIKE '%abc'(左模糊)- 对字段使用函数:
WHERE YEAR(create_time) = 2024 - 类型隐式转换:
VARCHAR字段传数字 - OR连接条件未全部使用索引
- 最左前缀原则破坏:联合索引
(a,b,c),查询WHERE b=1 AND c=2
本文通过幽默对话形式讲解Java面试高频考点,适合初学者查漏补缺,也提醒开发者夯实基础,别做“谢飞机”。