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

41 阅读5分钟

面试现场:大厂Java岗的“灵魂拷问”

面试官(推了推眼镜):欢迎来我们公司面试,先简单自我介绍一下吧。

谢飞机(挠头):我叫谢飞机,三年Java开发经验,会写for循环,能跑通Hello World,熟练使用Ctrl+CCtrl+V……

面试官(皱眉):咳咳,咱们进入正题。第一轮问题,关于Java核心和多线程。

第一轮:基础不牢,地动山摇

  1. 面试官:说说你对Java线程池的理解,为什么不用new Thread

    谢飞机:啊?线程池?那不是池塘养鱼吗?我们项目都是new Thread(),感觉挺快的,就是服务器经常炸……但重启一下就好了!

    面试官(扶额):……那你至少知道RunnableThread的区别吧?

    谢飞机:哦!这个我会!Runnable是接口,Thread是类,就像爸爸和儿子的关系!

    面试官(勉强点头):嗯……勉强算对一半。

  2. 面试官:那你说说ExecutorService常用的实现类有哪些?

    谢飞机:有FixedThreadPoolCachedThreadPool,还有那个……SingleThreadExecutor!我背过!

    面试官(略带欣慰):不错,那这些线程池的核心参数你知道吗?比如核心线程数、最大线程数?

    谢飞机:核心线程数就是核心的,最大线程数就是最大的……(陷入沉思)具体咋配?我们都是默认的!

    面试官:……行吧。

  3. 面试官:如果任务很多,线程池怎么处理?

    谢飞机:加机器呗!不行就堆new Thread,人多力量大!

    面试官(叹气):这是在拼资源,不是在写代码……


第二轮:JUC与并发进阶

面试官:接下来聊聊ConcurrentHashMap,它和HashMap有什么区别?

谢飞机:哦!这个我知道!HashMap不能多线程用,会死锁!我们组长说的!

面试官:准确说是可能扩容时形成环链导致死循环,JDK8之后改用红黑树和CAS+synchronized优化了。

谢飞机:对对对!就是那个……红什么树!我们没遇到过,因为我们不用HashMap做并发。

面试官:那你们用什么?

谢飞机:用new HashMap()synchronized块!

面试官:……那你了解ReentrantLocksynchronized的区别吗?

谢飞机synchronized是关键字,ReentrantLock是类,可以lock()unlock(),还能尝试锁!我看过源码……注释!

面试官(点头):还行。那CountDownLatchCyclicBarrier呢?

谢飞机:都是等人的!一个是一次性门禁,一个是循环打卡机!

面试官(居然笑了):比喻得……还挺形象。


第三轮:Spring全家桶与中间件

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

谢飞机singletonprototype,还有requestsession

面试官:很好。那Bean的生命周期?

谢飞机:出生、长大、工作、死亡……哦不对,是实例化、填充、初始化、销毁!

面试官:那@Autowired@Resource有什么区别?

谢飞机@Autowired按类型,@Resource按名字!名字优先!

面试官(满意):不错。那Redis持久化机制?

谢飞机:RDB是拍快照,AOF是记日记!我们线上只开RDB,怕AOF太大!

面试官:MySQL索引失效场景?

谢飞机:like左边有%、函数操作字段、类型转换……我背过八股文!

面试官(微笑):今天就到这里,你的基础还算扎实,虽然有些地方需要加强。回去等通知吧。

谢飞机(激动):好嘞!我回去就把new Thread全换成线程池!


参考答案详解

1. Java线程池核心参数

线程池核心参数由ThreadPoolExecutor构造函数定义:

public ThreadPoolExecutor(
    int corePoolSize,          // 核心线程数,常驻线程
    int maximumPoolSize,       // 最大线程数,临时扩容上限
    long keepAliveTime,        // 非核心线程空闲存活时间
    TimeUnit unit,
    BlockingQueue<Runnable> workQueue,  // 任务队列
    ThreadFactory threadFactory,         // 线程工厂
    RejectedExecutionHandler handler     // 拒绝策略
)
  • corePoolSize:核心线程即使空闲也不会被回收(除非设置allowCoreThreadTimeOut
  • maximumPoolSize:最大线程上限
  • workQueue:常见有ArrayBlockingQueue(有界)、LinkedBlockingQueue(无界)、SynchronousQueue(直接传递)
  • 拒绝策略AbortPolicy(抛异常)、CallerRunsPolicy(调用者线程执行)等

使用线程池优势:避免频繁创建销毁线程、控制并发数、提高资源利用率。

2. ConcurrentHashMap vs HashMap

| 对比项 | HashMap | ConcurrentHashMap | |--------|--------|------------------| | 线程安全 | 否 | 是 | | 实现方式 | JDK7:分段锁;JDK8:CAS + synchronized + 红黑树 | | 扩容机制 | 单线程rehash | 多线程协助迁移(transfer) | | 迭代器 | fail-fast | fail-safe |

3. ReentrantLock vs synchronized

  • synchronized:JVM层面,自动释放,不可中断,非公平
  • ReentrantLock:API层面,需手动unlock(),支持中断、超时、公平锁

4. CountDownLatch vs CyclicBarrier

  • CountDownLatch:计数器减到0后触发,一次性,适用于等待多个任务完成
  • CyclicBarrier:计数器加到阈值后触发,可重用,适用于多线程同步到达某点

5. Spring Bean生命周期

  1. 实例化(Instantiation)
  2. 属性赋值(Populate)
  3. 初始化前(BeanPostProcessor#postProcessBeforeInitialization)
  4. 初始化(InitializingBean#afterPropertiesSet 或 @PostConstruct)
  5. 初始化后(BeanPostProcessor#postProcessAfterInitialization)
  6. 使用
  7. 销毁(DisposableBean#destroy 或 @PreDestroy)

6. Redis持久化

  • RDB:定时快照,恢复快,可能丢失数据
  • AOF:记录每条写命令,数据更安全,文件大,恢复慢
  • 建议:生产环境同时开启,RDB用于备份,AOF用于灾难恢复

7. MySQL索引失效场景

  • LIKE '%abc'(左模糊)
  • 对字段使用函数:WHERE YEAR(create_time) = 2024
  • 类型隐式转换:VARCHAR字段传数字
  • OR连接条件未全部使用索引
  • 最左前缀原则破坏:联合索引(a,b,c),查询WHERE b=1 AND c=2

本文通过幽默对话形式讲解Java面试高频考点,适合初学者查漏补缺,也提醒开发者夯实基础,别做“谢飞机”。