# 1. 手写线程池,任务队列、Worker 循环、拒绝策略、优雅关闭如何实现? A shutdown 会中断所有正在执行的任务 B 拒绝策略只在队列满时触发,与线程数无关 C shutdownNow 会等待任务自然完成 D shutdown 不再接受新任务,但等待已提交任务完成 ✓ 正确答案
# 2. 手写一个可重入锁(基于 synchronized 或 AQS 思路)并说明重入计数的作用? A 重入计数用于让锁在嵌套时也能被正确释放 ✓ 正确答案 B 重入计数越大锁越安全 C 可重入锁不允许同一线程重复加锁 D 释放时无需检查持有者
# 3. ThreadLocal 的实现原理,ThreadLocalMap 的线性探测与弱引用 Entry 如何导致内存泄漏,如何正确清理? A 弱引用 key 回收后 value 仍可能残留,造成泄漏 ✓ 正确答案 B Entry 的 key 是强引用,ThreadLocal 不会回收 C 用完 remove 反而增加泄漏风险 D 线程池中线程复用不会泄漏
# 4. 手写 CountDownLatch 与 CyclicBarrier,基于 AQS 共享锁与栅栏重置(Generation)的核心差异如何? A CyclicBarrier 通过 Generation 实现可重置 ✓ 正确答案 B CountDownLatch 可以重复使用 C CyclicBarrier 是一次性的 D CountDownLatch 基于 ReentrantLock + Condition
# 5. 手写 AQS 简化版,CLH 等待队列、独占/共享模式的 acquire/release A acquire 失败时线程直接返回 B 共享模式不需要唤醒后继 C release 通过唤醒后继节点让等待线程继续 ✓ 正确答案 D CLH 队列用数组存储等待线程
# 7. 手写一个限流器(令牌桶/滑动窗口)并对比两种算法的内存与精度? A 令牌桶无法控制平均速率 B 滑动窗口内存比令牌桶更小 C 令牌桶精度比滑动窗口更高 D 令牌桶支持一定突发流量 ✓ 正确答案
# 8. 手写 Semaphore,AQS 共享计数的 acquire/release 与公平/非公平模式的实现差异如何? A 非公平模式会检查队列中是否有等待者 B 公平模式吞吐总比非公平高 C 公平模式允许新线程插队 D 公平模式保证先到先得,避免饥饿 ✓ 正确答案
# 9. 手写工作窃取(Work-Stealing)线程池或 ForkJoinPool 的分治模型,窃取为什么从队尾? A 窃取者从队头取任务以获得最新任务 B 工作窃取必须用全局锁保护 C 窃取从队尾会使任务重复执行 D 窃取从队尾减少与拥有者的竞争,且偏向取大任务 ✓ 正确答案
# 10. 手写支持超时与中断的锁,LockSupport.parkNanos 与 wait/notify 相比的可靠性差异如何? A unpark 提前于 park 执行时信号会丢失 B LockSupport 不受锁约束,且 unpark 有许可计数不会丢信号 ✓ 正确答案 C wait 不需要在循环中检查条件 D parkNanos 不支持响应中断
# 11. 手写线程池时如何埋点监控(任务数、队列深度、拒绝数)与告警 A 队列深度反映积压情况,可预警线程池耗尽 ✓ 正确答案 B 拒绝数不影响资源耗尽判断 C 指标计数必须用全局锁 D 活跃线程数一定等于 maxPoolSize
# 12. 手写线程池时如何支持"核心线程超时回收"(allowCoreThreadTimeOut)与动态调整 corePoolSize,空闲线程的 keepAlive 如何实现? A 核心线程永远不会空闲回收 B keepAlive 用 take() 实现 C allowCoreThreadTimeOut 让核心线程空闲后也能被回收 ✓ 正确答案 D 调整 corePoolSize 不影响已在线程
# 13. 手写一个异步任务编排器(依赖 DAG),任务间的依赖、失败传播与超时如何实现,与 CompletableFuture 的 thenCombine/allOf 对应关系如何? A 失败只影响自身不影响后继 B 任务前置全部完成后才就绪执行 ✓ 正确答案 C thenCombine 与 allOf 表示"任一个完成"即可 D 超时任务无需处理
# 14. 手写线程池的拒绝策略扩展,如何实现"重试入队""降级到其他池""优雅降级"三种自定义策略,各自适用什么场景? A 重试入队适合愿意等待并避免丢任务的场景 ✓ 正确答案 B 降级到其他池会丢弃任务 C 优雅降级就是抛异常 D 拒绝策略只能用于默认线程池
# 15. 手写"生产者-消费者",如何避免忙等与信号丢失? A 信号丢失不影响正确性 B 忙等比阻塞等待更省 CPU C 条件等待需要在循环中检查条件,避免信号丢失 ✓ 正确答案 D 生产者-消费者必须使用自旋
# 16. 手写 FutureTask 简化版,状态机(NEW/RUNNING/DONE/CANCELLED)与等待唤醒如何实现? A 状态不需要 volatile B 取消后仍可执行任务 C 状态为 DONE 时 get 才能返回 ✓ 正确答案 D RUNNING 状态可被多次执行
# 17. 手写读写锁的升级/降级边界,为什么读锁不能升级为写锁,写锁降级为何安全? A ReentrantReadWriteLock 支持读锁升级 B 写锁降级为读锁可能死锁 C 读锁升级写锁是安全的 D 读锁升级为写锁可能造成死锁 ✓ 正确答案
# 18. 手写 Ticket Lock(公平自旋锁)与自旋锁在临界区极短场景的应用 A 自旋锁在临界区极长时也高效 B Ticket Lock 是公平的,先取号先获得 ✓ 正确答案 C 自旋锁在单核下表现最好 D 自旋锁会阻塞线程
# 19. 手写"带超时的阻塞队列",offer(timeout) 与 poll(timeout) 的底层条件等待如何实现,与 ThreadPoolExecutor 的 workQueue 如何配合? A 非核心线程用 workQueue.poll(keepAliveTime) 实现空闲回收 ✓ 正确答案 B 核心线程用 poll 而非 take C awaitNanos 无需循环重算剩余时间 D 超时队列不能用于线程池