面试官:Java线程池的核心参数了解吗?谢飞机:会用new Thread就不错了!

32 阅读3分钟

第一轮:线程与线程池

面试官:请介绍一下Java中线程池的核心参数。

谢飞机:嗯……线程池?是不是就是把很多线程放在一起,像池子一样?我一般都直接 new Thread(),跑起来挺快的!

面试官:……那你至少知道 Executors 提供的几种常见线程池吧?

谢飞机:哦!这个我知道!有 FixedThreadPool、CachedThreadPool,还有 SingleThreadExecutor,我都背过!

面试官:不错,那你说说它们分别适用于什么场景?

谢飞机:Fixed 是固定数量的,适合任务多但不想开太多线程;Cached 是随用随开,适合短任务;Single 就是一个线程,按顺序执行。我这回答可以加薪了吧?

面试官(点头):基本概念还行。


第二轮:并发容器与锁机制

面试官:如果多个线程同时读写 HashMap 会有什么问题?

谢飞机:会……会吵架!数据乱掉,可能还抛 ConcurrentModificationException。

面试官:那怎么解决?

谢飞机:可以用 synchronized 包一下,或者用 ConcurrentHashMap!它线程安全,性能还好!

面试官:ConcurrentHashMap 在 JDK 1.8 之后是怎么实现线程安全的?

谢飞机:呃……它是……把数组分段了?每段上锁?不对……好像是用了 synchronized 和 CAS?哎呀,反正就是又锁又原子操作,贼牛!

面试官(皱眉):差不多吧……


第三轮:Spring 与分布式组件

面试官:Spring 中 Bean 的作用域有哪些?

谢飞机:singleton 和 prototype 我最熟!一个全局一个每次新建。

面试官:Spring Boot 自动装配的原理?

谢飞机:就是 @EnableAutoConfiguration,它会扫描 META-INF/spring.factories,把配置类加载进来!我知道它用了 SpringFactoriesLoader!

面试官:Redis 在项目中一般用来做什么?

谢飞机:存 session、做缓存、还能当分布式锁!我们公司连用户登录都靠它!

面试官:用 Redis 做分布式锁需要注意什么?

谢飞机:呃……要设过期时间,不然死锁了怎么办?还有……要用 SETNX?不对,现在都用 SET EX PX NX 加唯一值,再用 Lua 脚本释放……哎,细节太多了我记不清了!

面试官(叹气):今天先到这里,你回去等通知吧。

谢飞机(小声嘀咕):等通知=没戏,懂的都懂……


答案详解

1. 线程池核心参数

Java 线程池 ThreadPoolExecutor 有七大核心参数:

  • corePoolSize:核心线程数,即使空闲也不会销毁(除非设置 allowCoreThreadTimeOut)
  • maximumPoolSize:最大线程数
  • keepAliveTime:非核心线程空闲存活时间
  • unit:时间单位
  • workQueue:任务队列,如 LinkedBlockingQueue、ArrayBlockingQueue
  • threadFactory:线程创建工厂
  • handler:拒绝策略,如 AbortPolicy、CallerRunsPolicy

Executors 创建的线程池存在风险,例如 FixedThreadPool 使用无界队列可能导致 OOM,因此推荐手动创建 ThreadPoolExecutor。

2. ConcurrentHashMap 实现原理(JDK 1.8)

  • 底层采用 Node 数组 + 链表/红黑树
  • 使用 synchronized 对链表头节点或红黑树根节点加锁,替代 JDK 1.7 的分段锁
  • 插入时使用 CAS + synchronized 保证线程安全
  • 扩容时使用 CAS 标记扩容状态,支持多线程协助迁移

优势:锁粒度更细,性能更高,尤其在高并发读场景下表现优异。

3. Redis 分布式锁注意事项

  • 使用 SET key unique_value NX EX max_lock_time 命令保证原子性
  • unique_value 通常为 UUID 或线程ID,防止误删
  • 设置合理的超时时间,避免业务未执行完锁已释放
  • 释放锁时需用 Lua 脚本确保判断和删除的原子性:
    if redis.call('get', KEYS[1]) == ARGV[1] then
        return redis.call('del', KEYS[1])
    else
        return 0
    end
    
  • 可结合 RedLock 算法提升可靠性,但需权衡复杂性与收益。