2026-05-14 18:09:03
以下是针对字节跳动Java研发面试中线程、MySQL、Spring、JVM相关问题的整理与解答:
一、线程相关为什么要用线程池?
改进响应时间:线程池中的线程预先创建并等待任务分配,避免频繁新建线程的开销。
资源复用:减少CLR(或JVM)为短生命周期任务创建线程的开销,任务完成后回收资源。
优化线程调度:根据系统运行进程动态调整线程时间片。
统一管理:支持批量任务执行,避免为每个线程单独设置属性。
状态传递:允许通过对象引用传递任务状态信息。
限制并发量:解决特定场景下最大线程数限制问题。
什么是线程死锁?如何产生?如何避免?
死锁定义:两个或多个线程互相持有对方所需资源,导致永久阻塞。
产生条件:
互斥条件:资源独占,一次只能由一个线程占用。
请求与保持:线程持有资源时继续请求新资源。
不可剥夺:资源未释放前无法被其他线程强制获取。
循环等待:线程形成资源请求环路(如A等B,B等A)。
避免方法:
统一加锁顺序:所有线程按固定顺序获取锁。
加锁时限:设置超时时间,超时后释放已持有锁并重试。
死锁检测:通过数据结构(如锁依赖图)动态检测并解除死锁。
查询优化策略
避免全表扫描:在WHERE、ORDER BY涉及的列上建立索引。
慎用不等操作符:避免在WHERE中使用!=或<>,否则引擎放弃索引。
优先使用数字字段:数值型字段比字符型查询效率更高,存储开销更小。
明确字段列表:用SELECT 字段名替代SELECT *,减少不必要的数据传输。
减少临时表操作:避免频繁创建和删除临时表,降低系统资源消耗。
索引使用注意事项
索引并非越多越好,需权衡查询速度与写入性能。
复合索引需遵循最左前缀原则(如索引(A,B)对WHERE A=1有效,但对WHERE B=1无效)。
Bean的作用域
Singleton:默认作用域,全局唯一实例(如配置文件中的单例Bean)。
Prototype:每次请求创建新实例(如无状态服务)。
Request:单次HTTP请求内有效(Web应用)。
Session:单个HTTP Session内有效(用户会话相关数据)。
Global Session:Portlet环境中全局有效(较少使用)。
Spring中应用的设计模式
代理模式:AOP和远程调用(如JDK动态代理)。
单例模式:默认Bean作用域。
模板方法模式:简化重复代码(如JdbcTemplate)。
前端控制器模式:DispatcherServlet分发请求。
依赖注入模式:通过BeanFactory/ApplicationContext管理对象。
工厂模式:BeanFactory创建Bean实例。
Spring MVC核心与流程
核心:控制反转(IoC)和面向切面编程(AOP)。
请求处理流程:
用户请求→DispatcherServlet(前端控制器)。
根据URL选择Controller(页面控制器)。
Controller处理请求,返回ModelAndView。
DispatcherServlet根据视图名渲染响应。
内存区域划分
虚拟机栈:线程私有,存储方法调用的栈帧(局部变量、操作数栈等)。
堆:线程共享,存放对象实例(GC主要区域)。
方法区:线程共享,存储类信息、常量、静态变量(JDK 8后改为元空间)。
程序计数器:线程私有,记录当前线程执行的字节码行号。
本地方法栈:线程私有,服务Native方法调用。
关键点
堆和方法区是线程共享资源,需考虑并发访问的线程安全问题。
虚拟机栈和本地方法栈溢出会抛出StackOverflowError,堆溢出会抛出OutOfMemoryError。
面试前可结合实际项目经验,准备具体案例(如用线程池优化接口响应、通过索引解决慢查询等),以体现问题解决能力。