面灵AI

BIGO Java 后端一面:幂等、线程池与百亿数据 Top K

轮次
一面
时间
2026-09
来源
牛客网

《面试题目》

  1. 能否介绍一下自己,以及项目中的技术难点?
  2. 解决项目问题时,有没有比较过其他方案?
  3. 幂等是什么,如何实现,为什么这些方案能够保证幂等?
  4. 状态机是什么,怎样保证状态按合法路径流转?
  5. 生产环境能否使用 Java 同步锁?
  6. 乐观锁是什么,原理是什么,为什么能控制并发修改?
  7. 线程池的执行流程是什么,有哪些重要参数?
  8. 为什么使用 Executors 工具类创建线程池时需要谨慎?
  9. execute 与 submit 有什么区别,submit 返回什么,调用 get 会阻塞吗?
  10. synchronized 有哪些优化机制,锁升级在什么条件下发生?
  11. MySQL 快照读与当前读有什么区别,快照读如何实现?
  12. Kafka 消费组重平衡由什么触发,如何减少不必要的重平衡?
  13. 什么是线程安全,SimpleDateFormat 是否线程安全?
  14. 如何安全地并发使用日期格式化功能,除同步加锁外还有什么方案?
  15. volatile 有什么作用,底层怎样实现这些保证?
  16. JVM 哪些运行时数据区可能发生 OOM,程序计数器有什么特殊之处?
  17. Java 中哪些情况可能形成死锁,如何避免?
  18. 什么是覆盖索引,哪些情况下索引无法有效用于查询?
  19. IN 与 NOT IN 条件是否会使用索引?
  20. LIMIT 有哪些参数,分页时会遇到什么问题?
  21. HashSet 与 TreeSet 的底层结构有什么区别,是否允许 null 元素?
  22. Cookie、Session 与 Token 有什么区别,Token 可以怎样实现?
  23. Session 是否有状态,如何设计不依赖逐会话服务端存储的认证方式?
  24. 如何从 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 状态问题,均未保留足够条件,无法还原具体题目。