BIGO Java 后端一面:幂等、线程池与百亿数据 Top K
- 轮次
- 一面
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- 能否介绍一下自己,以及项目中的技术难点?
- 解决项目问题时,有没有比较过其他方案?
- 幂等是什么,如何实现,为什么这些方案能够保证幂等?
- 状态机是什么,怎样保证状态按合法路径流转?
- 生产环境能否使用 Java 同步锁?
- 乐观锁是什么,原理是什么,为什么能控制并发修改?
- 线程池的执行流程是什么,有哪些重要参数?
- 为什么使用 Executors 工具类创建线程池时需要谨慎?
- execute 与 submit 有什么区别,submit 返回什么,调用 get 会阻塞吗?
- synchronized 有哪些优化机制,锁升级在什么条件下发生?
- MySQL 快照读与当前读有什么区别,快照读如何实现?
- Kafka 消费组重平衡由什么触发,如何减少不必要的重平衡?
- 什么是线程安全,SimpleDateFormat 是否线程安全?
- 如何安全地并发使用日期格式化功能,除同步加锁外还有什么方案?
- volatile 有什么作用,底层怎样实现这些保证?
- JVM 哪些运行时数据区可能发生 OOM,程序计数器有什么特殊之处?
- Java 中哪些情况可能形成死锁,如何避免?
- 什么是覆盖索引,哪些情况下索引无法有效用于查询?
- IN 与 NOT IN 条件是否会使用索引?
- LIMIT 有哪些参数,分页时会遇到什么问题?
- HashSet 与 TreeSet 的底层结构有什么区别,是否允许 null 元素?
- Cookie、Session 与 Token 有什么区别,Token 可以怎样实现?
- Session 是否有状态,如何设计不依赖逐会话服务端存储的认证方式?
- 如何从 100 亿个数字中找出第 100 大的数,同时尽量节省内存?
《参考解析》
幂等要落到同一个业务动作上
同一请求重试,应该识别出它还是那笔订单或那次操作。可以给业务动作设置唯一键,在存储层用唯一约束或带状态条件的更新决定谁执行成功;后续重复请求返回已有结果。只在应用里先查再写,两个请求仍可能同时通过检查。状态机也类似:更新时同时校验旧状态,不能把“先读状态、再无条件覆盖”当成原子流转。
本地锁能用,但它只管本地竞争
synchronized 可以用于生产环境,关键是共享资源和竞争线程是否都在同一 JVM、是否使用同一个监视器。多实例各自加锁,不能保护共同访问的数据库记录。锁内若有慢网络请求,会放大等待时间;应该先明确临界区,再决定锁的粒度。
快照读与当前读可能看到不同版本
InnoDB 的普通一致性读通过读视图和历史版本确定可见记录;在可重复读级别,同一事务的一致性读通常沿用首次一致性读建立的快照。锁定读则按最新状态读取并加锁,不能认为它必然得到与此前普通 SELECT 一样的结果。可以对照 InnoDB 事务隔离级别文档 理解两类读取的差别。
submit 返回的是任务句柄
submit 返回 Future,可以查询完成状态、取消任务或取得结果。任务尚未完成时,普通 get 会等待;任务失败时,异常通过 Future 暴露给调用者。因此提交后既不保留 Future、也不在任务内部记录异常,很容易丢掉失败信息。对仅需异步执行的任务,也要明确错误由谁观察。
第 100 大只需要维护 100 个候选值
逐个读取数字,维护容量为 100 的最小堆。堆未满就插入;堆满后,只有比堆顶更大的数字才替换堆顶。遍历结束时堆顶就是第 100 大,时间复杂度 O(N log 100),额外空间 O(100),无须把 100 亿个数全部装入内存。
实现前要确认重复值是否占名次;如果要求第 100 个不同的数,还需要对候选值去重。原帖另提到一道零钱兑换变体,以及没有听清的 TCP 状态问题,均未保留足够条件,无法还原具体题目。