跳转到内容

腾讯一面

💡

腾讯一面完整面试复盘(25题)。覆盖多线程编程、Java并发、集合源码、Spring事务、MySQL隔离级别、分布式事务、Redis实战、项目经验。每道题附带详细解析。


一、多线程编程题

Q1-3:交替打印线程 + 信号量 + 可重入锁

📝

题目:两个线程交替打印字符串。面试者用两个Semaphore解决,面试官追问:两字符串长度不一致怎么办?为什么不用ReentrantLock?

Semaphore方案

ReentrantLock为什么不是首选?

  • Semaphore天然适合"许可"模型(线程1许可=可打印,线程2许可=可打印)
  • ReentrantLock配合Condition也能实现,但需要两个Condition + 一个状态变量,代码更复杂
  • 可重入锁(ReentrantLock)的含义:同一线程可以多次获取同一把锁而不会死锁。synchronized也是可重入的。用于递归调用或嵌套调用同一把锁的场景

Q4-5:多线程扩展 + 原子类

📝

追问:如果有多个线程呢?Java原子类有哪些?

  • 多线程扩展:N个线程交替打印 → 用N个Semaphore循环释放,或使用AtomicInteger标记当前轮到谁;策略模式优化:将"轮到谁"的判断逻辑抽象为策略接口,不同规则实现不同策略
  • 原子类:AtomicInteger/Long/Boolean(基本类型)、AtomicReference(引用)、AtomicStampedReference(带版本号解决ABA)、LongAdder(高并发累加优于AtomicLong)

二、HashMap与ConcurrentHashMap

Q7-8:底层原理 + 时间复杂度

📝

关键纠正:面试者说HashMap操作都是O(1),面试官反问"确定吗?"——HashMap在hash碰撞严重时退化到O(n)(链表)或O(log n)(红黑树)。

操作

平均

最坏

get/put/remove

O(1)

O(n)链表 / O(log n)红黑树

ConcurrentHashMap核心要点

  • JDK7:分段锁(Segment extends ReentrantLock),16段,并发度16
  • JDK8:CAS + synchronized锁桶头节点,锁粒度更细。put时桶空CAS写入,桶非空synchronized锁头节点。get无锁(volatile保证可见性)
  • 不允许null键值:防止并发环境下的二义性(get返回null无法区分"不存在"和"值为null")

三、线程池与并发基础

Q9-10:线程创建方式 + 拒绝策略

📝

线程创建4种方式:继承Thread、实现Runnable、实现Callable+FutureTask、线程池(ExecutorService)。

4种拒绝策略:AbortPolicy(抛异常,默认)、CallerRunsPolicy(调用者线程执行)、DiscardPolicy(直接丢弃)、DiscardOldestPolicy(丢弃队首)。

Q11:BIO vs NIO

BIO

NIO

模型

阻塞IO,一个连接一个线程

非阻塞IO,一个线程管理多个连接(Selector)

核心

ServerSocket + Socket

Channel + Buffer + Selector

场景

连接数少且固定的架构

高并发、连接数多但数据量短的场景


四、Spring核心

Q12-13:Bean生命周期 + 事务

Bean生命周期:实例化 → 属性注入 → Aware回调 → BeanPostProcessor前置 → @PostConstruct → InitializingBean → BeanPostProcessor后置 → 就绪 → @PreDestroy → 销毁

事务传播(7种):REQUIRED(默认,加入或新建)、REQUIRES_NEW(挂起当前新建)、NESTED(savepoint嵌套)、SUPPORTS/NOT_SUPPORTED/NEVER/MANDATORY

Q15-16:事务失效场景

💡

同类方法调用事务失效:this.methodB()不经过代理对象,事务不生效。解决:注入自身 → 调用代理对象的方法;或AopContext.currentProxy();或将方法拆分到不同Service。

异步方法事务:@Async + @Transactional不能直接用在一个方法上,因为异步是新线程,事务不会传播到新线程。


五、MySQL事务

Q14:四种隔离级别

级别

解决的问题

存在的问题

READ UNCOMMITTED

脏读、不可重复读、幻读

READ COMMITTED

脏读

不可重复读、幻读

REPEATABLE READ(MySQL默认)

脏读、不可重复读

幻读(MVCC+间隙锁基本解决)

SERIALIZABLE

全部

性能极低


六、分布式事务

Q17:微服务间如何实现分布式事务?

📝

核心方案:

  • Seata(AT/TCC/Saga模式):AT自动回滚、TCC手动confirm/cancel、Saga长事务补偿
  • 本地消息表 + MQ:本地事务中写消息表 → 定时任务扫描未发送消息 → MQ投递 → 消费端幂等处理
  • RocketMQ事务消息:半消息→本地事务→commit/rollback
  • 最终一致性 > 强一致性:分布式系统中优先保证最终一致性,配合补偿机制和监控告警

七、项目深挖(海报渲染 + 排行榜 + 消息推送)

Q19-21:海报渲染超时兜底

  • 重试+MQ:超时后放入MQ延迟队列,消费者重试渲染
  • 一直超时的降级:返回默认海报模板(静态图)、降级为纯文字卡片、异步通知用户稍后查看
  • 业务层面:预生成常用海报模板并缓存、限制海报复杂度(最大图层数/最大渲染时长)

Q22-25:Redis Zset排行榜 + 消息推送

  • Zset key/value:key=step_rank:{date}:{slot},member=user:{id},score=复合分数(分数×1e13+时间编码)
  • 防重复发送:消息表+唯一索引、Redis SETNX做幂等、消息ID去重
  • Zset内存优化:ziplist编码(小数据)、数据TTL过期、冷热分离(Redis热+ES/Hive冷)、Redis Cluster水平分片
  • Redis挂了怎么办:Redis Cluster自动故障转移(Sentinel)、本地缓存兜底、MQ消息持久化保证不丢、RDB+AOF持久化

面试总结:腾讯一面的广度较大(多线程→集合→Spring→MySQL→分布式→项目),核心考察实战经验和技术深度。HashMap复杂度纠正、事务失效场景、分布式事务方案、Redis降级方案是区分度较高的点。