字节跳动 Java 后端 社招一面:ThreadLocal、锁与找重复数
- 轮次
- 一面
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
- 做一个简短的自我介绍。
- 这两份工作换工作的主要原因是什么?
- 挑几个你觉得做得不错的项目介绍一下,重点讲边界和实现。
- Java 的 ThreadLocal 是怎么实现的?
- ThreadLocal 底层怎么实现,怎么控制?
- 它跟普通的 Map 或数组有什么区别?
- 它怎么实现线程隔离?
- 怎么定位 ThreadLocal 相关的问题?
- Java 里实现本地锁有哪几种方法?
- synchronized 的底层实现是什么?
- 如果要实现服务端锁,要怎么做?
- 锁的过期时间怎么决定,设多少合适?
- 算法:找重复数。
《参考解析》
ThreadLocal:每个 Thread 内部有一个 ThreadLocalMap,key 是 ThreadLocal 的弱引用,value 是强引用。get() 以当前线程为入口取 map,再以 ThreadLocal 为 key 查值,所以天然线程隔离。它和普通 Map 的区别是「每个线程一份」,不是共享容器。常见问题是线程池里线程复用导致脏数据,必须在 finally 里 remove();key 是弱引用,但 value 是强引用,不及时清理仍可能泄漏。跨线程传递可以用 InheritableThreadLocal,线程池场景更适合 TransmittableThreadLocal 或手动透传上下文。
锁:本地锁有 synchronized、ReentrantLock、StampedLock、Atomic/CAS、CountDownLatch 等。synchronized 底层是对象头 Mark Word 加 Monitor,JDK 6 之后有偏向锁、轻量级锁、重量级锁的升级(新版本偏向锁已废弃)。服务端锁常用 Redis SET NX EX 或 Redisson,ZooKeeper 也能做。过期时间要大于业务最大执行时间,并留余量;更稳的是看门狗续期 + 业务幂等,不能只靠一个固定 TTL。
找重复数:如果数组长度 n+1、数字范围 1..n、只有一个重复,可以用快慢指针找环入口,时间 O(n)、空间 O(1);也可以用二分按抽屉原理统计。若允许修改数组,可以用下标取负标记。答题前先确认约束:是否只有一个重复、是否允许修改、数字范围、是否要求空间复杂度。面试官往往在考你澄清问题的能力,不要上来就写。