25年12月北京清大科越 Java后端开发工程师 一面
1. 死锁四个必要条件:互斥、持有等待、不可抢占、循环等待
思路
先解释每个条件的核心含义,口语化讲清“缺一不可”,突出理解而非死记。
回答示例
面试官您好,死锁必须同时满足这四个条件,少一个都不会发生:
第一,互斥:资源只能被一个线程占着,别人用不了,比如一把锁只能一个线程拿;
第二,持有等待:线程拿着一把锁,还等着拿另一把,不释放手里的;
第三,不可抢占:线程拿了锁,除非自己放,别人抢不走;
第四,循环等待:线程A等线程B的锁,线程B等线程A的锁,形成闭环。
只要打破其中一个,比如让锁能抢占,或者避免循环等待,就能解决死锁。
2. ThreadLocal内存泄漏:弱引用+Map清理机制
思路
讲清“为什么泄漏”(弱引用+Entry不清理)、“怎么避免”(手动remove),逻辑要顺。
回答示例
ThreadLocal内存泄漏核心是两点:
第一,ThreadLocal的Entry里,key是对ThreadLocal的弱引用,如果ThreadLocal对象被回收,key就成null了,但Entry还在ThreadLocalMap里;
第二,如果线程一直存活(比如线程池的核心线程),这些null key的Entry不会自动清理,value还强引用着对象,就导致内存泄漏。
解决办法就是用完ThreadLocal后手动调用remove(),清空Entry;另外JDK也做了优化,get/set的时候会清理null key的Entry,减少泄漏风险。
3. Java三大特性:封装、继承、多态的实现方式
思路
逐个讲“是什么+怎么实现”,结合代码场景,不抽象。
回答示例
这三个是Java面向对象的核心,实现方式很清晰:
- 封装:把属性私有化(private),通过get/set方法访问,对外隐藏内部实现,比如User类的name私有,只能通过getName()拿,保证数据安全;
- 继承:用extends关键字,子类继承父类的属性和方法,还能重写,比如Student extends Person,复用Person的name、age,重写say()方法;
- 多态:核心是“父类引用指向子类对象”,比如Person p = new Student(),调用p.say()会执行子类的实现;还有接口实现也是多态,比如List list = new ArrayList()。
4. 异常处理:try-catch-finally执行顺序及finally执行条件
思路
讲清“正常/异常/return”三种场景的执行顺序,明确finally唯一不执行的情况。
回答示例
执行顺序分三种情况,finally的执行条件也很明确:
- 正常执行:先try里的代码,再finally,catch不执行;
- try抛异常:先try里出错的代码,再catch处理异常,最后finally;
- try里有return:先执行try里的代码到return,再执行finally,最后返回(如果finally里也return,会覆盖try的返回值);
finally唯一不执行的情况:线程被终止(Thread.stop())、JVM崩溃(比如System.exit(0)),其他情况哪怕抛异常、return,都会执行。
5. MySQL事务ACID:原子性如何保证?(redo log)
思路
核心讲redo log(重做日志)的“先写日志再写磁盘”,结合事务提交流程,口语化。
回答示例
MySQL事务的原子性(要么全做,要么全不做)主要靠redo log(重做日志) 保证:
执行事务时,先把修改操作记录到redo log里(内存+磁盘),再修改内存中的数据页;
如果事务执行中数据库崩了,重启后会根据redo log恢复未完成的操作,保证事务要么全部完成,要么全部回滚;
另外undo log也配合,回滚时用undo log撤销已
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本专栏在精不在多,内容分为八股文、大厂真实面经,面试通过后将offer和面试题私发给我,可退还专栏的收益部分费用。欢迎大家共建专栏
