# 1. 手写生产者-消费者中 wait/notify 与 BlockingQueue 两种实现的虚假唤醒防御? A notify 与 notifyAll 效果完全一致 B wait 放在 if 中即可 C BlockingQueue 需要手写 wait/notify D wait 必须放在 while 循环中,以防御虚假唤醒与条件变化 ✓ 正确答案
# 2. 三个线程交替打印 ABC 的多种实现(synchronized/Lock+Condition/Semaphore)? A synchronized 用 notifyAll 时无法靠状态判断 B Semaphore 用三个信号量初始 1,0,0,各自 acquire 后 release 下一个,形成轮转 ✓ 正确答案 C Lock+Condition 用 notifyAll 唤醒所有 D 三种实现都需要自旋
# 3. 手写令牌桶限流器(Token Bucket)中字段设计(capacity/rate/tokens/lastRefillTime)、tryAcquire 的原子性保证(CAS vs synchronized)、分布式场景下 Redis + Lua 的实现 A 分布式下用普通 Redis 操作即可保证原子性 B 令牌桶无需记录上次补充时间 C 用 lastRefillTime 惰性补充令牌,tryAcquire 需保证检查+更新的原子性 ✓ 正确答案 D tryAcquire 无需原子性
# 4. 手写 LRU Cache(LeetCode 146)中 HashMap + 双向链表的 O(1) get/put、边界处理(capacity=0、重复 key 更新)、线程安全版本的锁粒度选择(全局锁 vs 分段锁 vs ConcurrentHashMap + 链表锁) A 双向链表只支持 O(n) 删除 B HashMap 定位 + 双向链表 O(1) 删除任意节点,capacity=0 时 put 无效 ✓ 正确答案 C 重复 key 更新会新增节点 D get 未命中时也要移动链表
# 5. 手写限流的滑动窗口中如何用时间戳队列实现固定窗口与滑动窗口,边界请求如何处理? A 滑动窗口内存 O(1) B 固定窗口比滑动窗口更精确 C 滑动窗口用时间戳队列移除过期请求,避免固定窗口的边界突刺 ✓ 正确答案 D 滑动窗口无法处理边界请求
# 6. 手写时间轮/延迟任务调度器中环形数组加轮询指针如何调度延时任务,与 DelayQueue 堆实现的复杂度对比 A 时间轮用环形数组+指针,添加任务 O(1);DelayQueue 用堆,添加 O(log n) ✓ 正确答案 B 时间轮添加任务 O(log n) C DelayQueue 添加任务 O(1) D 时间轮无法处理大跨度延迟
# 7. 手写 Semaphore(计数信号量)中用 lock 加 condition 实现 acquire/release,为什么释放时要通知所有等待者? A acquire 用 while(permits<=0) await,release 用 signalAll 通知所有等待者 ✓ 正确答案 B release 只需 signal 一个等待者 C acquire 无需循环检查 D 释放后无需通知等待者
# 8. 手写线程安全的单例(双检锁 volatile 的必要性)? A volatile 防止实例创建时指令重排,避免暴露未初始化对象 ✓ 正确答案 B 双检锁无需 volatile C 第一层检查必须加锁 D volatile 只保证可见性,不涉及有序性
# 9. 设计一个线程安全的计数器,synchronized、AtomicLong、LongAdder 的性能层级? A AtomicLong 是阻塞式 B 高并发写场景性能层级为 LongAdder > AtomicLong > synchronized ✓ 正确答案 C LongAdder 单点竞争 D synchronized 在并发下性能最好
# 10. 手写 ReadWriteLock 中读读并发、读写互斥、写写互斥的状态位设计(高 16 位读锁/低 16 位写锁)、写锁降级与读锁升级的禁止原因、公平与非公平策略 A 读读互斥 B 读锁升级是被允许的 C 写锁降级被禁止 D 高 16 位读锁、低 16 位写锁;写锁可降级为读锁,读锁升级被禁止(防死锁) ✓ 正确答案
# 11. 手写 CountDownLatch 与 CyclicBarrier 中 AQS 的 state 计数与 await/signal 机制、CyclicBarrier 的代(generation)概念与 BrokenBarrierException、两者在并发测试框架中的应用 A CountDownLatch 一次性倒计数,CyclicBarrier 可重用且用 generation 表示每轮 ✓ 正确答案 B 两者都可无限重用 C CyclicBarrier 无中断异常 D CountDownLatch 的 state 递增
# 12. 多线程交替打印中用 volatile/自旋、锁与信号量、原子变量三种方案的对比? A 阻塞式会浪费 CPU B 自旋式在长等待时更高效 C volatile/自旋与原子变量是自旋式(不阻塞),锁/信号量是阻塞式(不耗 CPU) ✓ 正确答案 D 三种方案都需要锁
# 13. 手写限流器中令牌桶 vs 滑动窗口的精度、突发与内存复杂度对比? A 两者精度相同 B 令牌桶内存 O(n) C 滑动窗口允许突发 D 令牌桶允许突发、内存 O(1);滑动窗口精确但内存 O(窗口请求数) ✓ 正确答案
# 14. 手写 Future(带结果的异步任务)中如何用锁加条件变量保存结果、异常与取消状态? A get 无需等待即可返回 B 用锁+条件变量管理状态机,setResult 时唤醒、get 阻塞等待、cancel 标记并唤醒 ✓ 正确答案 C 异常无需纳入状态机 D cancel 后 get 返回 result
# 15. 手写线程池中任务队列、worker 线程与拒绝策略的完整实现? A worker 只执行一次任务 B 任务队列非阻塞 C 用阻塞队列存任务、worker 循环取任务执行,队列满时按拒绝策略处理 ✓ 正确答案 D 拒绝策略只在队列空时触发
# 16. 手写漏斗(leaky bucket)限流中恒定速率出水如何实现,与令牌桶在突发与内存上的差异 A 漏桶与令牌桶完全相同 B 漏桶允许突发超过速率 C 漏桶内存 O(n) D 漏桶以恒定速率出水、缓冲突发,与令牌桶(允许突发)不同 ✓ 正确答案
# 17. 生产者-消费者中用锁+条件变量与无锁队列(Ring Buffer)两种方式实现? A 锁式吞吐一定高于无锁 B 无锁 Ring Buffer 无需处理满的情况 C 锁式阻塞省 CPU,无锁 Ring Buffer 用 CAS+原子下标实现高吞吐 ✓ 正确答案 D 无锁 Ring Buffer 需要阻塞
# 18. 手写对象池/连接池中借出、归还与超时回收的状态管理,泄漏如何检测 A 借用集合用于存空闲对象 B 对象借出后无需记录 C 超时回收是多余的 D 维护空闲队列与借用集合,借出/归还切换状态,记录借用时间可检测泄漏 ✓ 正确答案
# 19. 设计多线程任务分发,生产者-消费者加结果聚合如何实现带依赖的任务执行,与线程池 submit 的取舍 A 独立任务用线程池 submit,带依赖任务用依赖计数/回调/DAG 调度 ✓ 正确答案 B 带依赖任务用线程池 submit 即可 C 结果聚合必须用共享变量 D 依赖任务按任意顺序执行