面试官问线程池的核心参数与执行流程一张图餐厅运营比喻彻底拿下这道必考题附图解比喻避坑指南预计阅读14分钟 你是不是也这样能说出corePoolSize、maximumPoolSize几个参数名但面试官一追问“corePoolSize和maximumPoolSize什么关系”“Executors有什么坑”“队列满了怎么办”就答不上来了今天一张图 一个餐厅运营故事 源码级解析 六道追问彻底拿下这道题。摘要线程池是Java并发编程的核心工具基于生产者-消费者模型实现线程复用。ThreadPoolExecutor有7大核心参数corePoolSize常驻核心线程、maximumPoolSize最大线程数、keepAliveTime空闲存活时间、unit时间单位、workQueue任务队列、threadFactory线程工厂、handler拒绝策略。任务执行遵循4步流程核心线程→任务队列→非核心线程→拒绝策略。生产环境禁止使用Executors创建线程池必须通过ThreadPoolExecutor手动配置避免OOM风险。一句话核心线程是“常驻员工”非核心线程是“临时工”任务队列是“待办清单”拒绝策略是“最后防线”。我是折哥《Java 85题图解版》系列连载中已更新37题建议收藏本系列。每周2-3篇85题通关路线一键追完。点击关注第一时间收到每篇新题推送。上一篇面试官问volatile和Atomic类的底层原理下一篇预告面试官问死锁的产生条件与排查方法待发布全部85题点击查看总目录关注专栏追更不迷路一句话总结核心线程是“常驻员工”非核心线程是“临时工”任务队列是“待办清单”拒绝策略是“最后防线”。corePoolSize核心线程数正式员工雷打不动即使没活干也留着 → 像餐厅的正式厨师无论有没有客人都在。workQueue工作队列排队等候区 → 像餐厅的等候区客人来了厨师都在忙就先在等候区坐下排队。maximumPoolSize最大线程数正式兼职的总数 → 像等候区坐满了餐厅叫兼职厨师来帮忙但总人数不能超过这个数。keepAliveTime空闲存活时间兼职的下班时间 → 像高峰期过了兼职厨师如果30分钟没事干就让他们走人正式员工继续留着。handler拒绝策略客流超限的应急预案 → 像客人太多正式兼职全忙等候区也满了拒绝策略决定怎么办。背诵口诀核心线程常驻岗任务队列来缓冲非核心线程临时忙拒绝策略最后挡。核心设计理念线程池 生产者-消费者模型——提交任务的线程是生产者池中的工作线程是消费者任务队列是缓冲区。 面试还原面试官你们项目里用线程池吗核心参数怎么配置的任务进来之后是怎么执行的这是Java并发面试中必问必考的核心题直接进入正题。 一图看懂线程池7大参数与4步流程 生活比喻餐厅运营场景设定你是一家餐厅线程池的老板负责接待顾客任务。corePoolSize 正式员工你雇了3名正式厨师corePoolSize3他们是你的核心团队。即使没有客人空闲状态这3个人也照常上班你不会开除他们。任务队列workQueue 排队等候区客人来了3个厨师都在忙新客人就在等候区任务队列坐下排队。等候区有10个座位有界队列坐满了就不能再进来了。maximumPoolSize 正式员工 临时工等候区坐满了还有客人来。你叫来2名兼职厨师非核心线程帮忙现在总共5个人在干活maximumPoolSize5。注意兼职厨师和正式厨师总人数不能超过5人maximumPoolSize是包括核心线程在内的总数。keepAliveTime 临时工的下班时间高峰期过了客人少了。兼职厨师如果30分钟keepAliveTime没事干就让他们下班。正式员工继续留着。拒绝策略handler 客人太多怎么办正式员工3人兼职2人全在忙等候区10个座位全满又来客人了怎么办你的应对方案拒绝策略决定怎么处理方案AAbortPolicy直接拒之门外说“今天不接待了”抛异常方案BCallerRunsPolicy让老板自己下厨做调用者线程执行方案CDiscardPolicy当没看见客人走了就算了静默丢弃方案DDiscardOldestPolicy把等候区最早来的客人请走让新客人进来丢弃最老任务一句话对照核心线程正式员工雷打不动非核心线程兼职忙时来闲时走任务队列等候区排队缓冲拒绝策略客流超限应急预案。 7大核心参数详解面试速查版完整构造方法publicThreadPoolExecutor(intcorePoolSize,// 核心线程数intmaximumPoolSize,// 最大线程数longkeepAliveTime,// 空闲存活时间TimeUnitunit,// 时间单位BlockingQueueRunnableworkQueue,// 工作队列ThreadFactorythreadFactory,// 线程工厂RejectedExecutionHandlerhandler// 拒绝策略){/* ... */}各参数详解参数含义关键点面试考点corePoolSize核心线程数常驻线程默认一直存活核心线程是“正式员工”maximumPoolSize最大线程数核心非核心的总上限非核心线程是“临时工”keepAliveTime空闲存活时间非核心线程空闲超时被回收可设置allowCoreThreadTimeOut(true)让核心线程也超时unit时间单位TimeUnit.SECONDS等—workQueue工作队列存放等待任务的阻塞队列有界队列防止OOMthreadFactory线程工厂创建线程可自定义名称/优先级建议自定义方便问题排查handler拒绝策略队列满且线程达上限时触发4种策略需区分 4种工作队列对比队列类型是否无界特点适用场景风险ArrayBlockingQueue❌ 有界数组实现FIFO任务量可控队列容量需合理设置LinkedBlockingQueue⚠️ 默认无界链表实现FIFO吞吐量要求高Executors默认用这个可能OOMSynchronousQueue❌ 不存储直接交给线程无缓存短任务、高并发需配合大maximumPoolSizePriorityBlockingQueue✅ 无界支持优先级排序任务有优先级需求无界可能OOMDelayQueue✅ 无界延迟执行定时任务/超时处理无界可能OOM 4种拒绝策略详解当线程池已满线程数达maximumPoolSize且队列已满或已关闭时触发。策略行为适用场景风险AbortPolicy默认抛出RejectedExecutionException关键任务必须被感知异常需妥善处理CallerRunsPolicy由提交任务的线程自己执行不允许丢任务的场景可能阻塞提交线程DiscardPolicy静默丢弃新任务非关键日志/监控数据任务丢失不可感知DiscardOldestPolicy丢弃队列中最老的任务再提交新任务可接受丢弃旧任务旧任务可能丢失️ 为什么禁止使用Executors生产铁律⭐很多面试者会用Executors.newFixedThreadPool()创建线程池但这是生产环境的致命陷阱。Executors的三大坑线程池类型潜在风险原因newFixedThreadPool()OOM风险使用无界LinkedBlockingQueue队列长度Integer.MAX_VALUE任务积压耗尽内存newSingleThreadExecutor()OOM风险同上无界队列newCachedThreadPool()OOM风险maximumPoolSize Integer.MAX_VALUE可创建无限线程耗尽内存阿里巴巴Java开发手册明确规定线程池不允许使用Executors创建必须通过ThreadPoolExecutor手动配置。 高频面试追问6道大厂真题追问1corePoolSize和maximumPoolSize有什么区别回答要点核心线程是常驻的非核心线程是动态的。详细回答corePoolSize是核心线程数这些线程会一直存活即使空闲也不会被销毁。maximumPoolSize是最大线程数是核心线程和非核心线程的总和。当任务量超过核心线程队列容量时线程池会创建非核心线程临时工来应对但这些线程空闲超过keepAliveTime后会被回收。追问2线程池的任务执行流程是怎样的最高频回答要点四步走——核心线程→任务队列→非核心线程→拒绝策略。详细回答① 当前线程数 corePoolSize→ 新建核心线程执行任务② 核心线程已满 → 任务进入workQueue排队等待③ 队列已满 → 当前线程数 maximumPoolSize→ 新建非核心线程执行任务④ 队列已满且线程数达maximumPoolSize→ 触发拒绝策略。追问3execute()和submit()有什么区别回答要点submit()可获取返回值execute()无返回值。详细回答execute()是Executor接口定义的方法提交Runnable任务无返回值。submit()是ExecutorService接口定义的方法可提交Runnable或Callable任务返回Future对象可通过Future.get()获取执行结果或异常。追问4如何合理设置线程池大小回答要点分CPU密集型和IO密集型计算。详细回答CPU密集型计算为主corePoolSize CPU核心数 1IO密集型网络/磁盘IO为主corePoolSize 2 × CPU核心数最佳实践通过压测确定观察吞吐量和响应时间找到最优配置混合型任务考虑分层设计——主线程池处理IO型任务子线程池处理计算型任务追问5核心线程会被回收吗回答要点默认不会但可通过参数开启。详细回答默认情况下核心线程不会被回收即使空闲也会一直存活。但可以通过allowCoreThreadTimeOut(true)开启核心线程超时回收此时核心线程空闲超过keepAliveTime后也会被销毁。追问6workQueue满了但线程数还没到maximumPoolSize会创建新线程吗回答要点会。队列满→创建非核心线程。详细回答会。workQueue.offer()返回false队列已满时线程池会尝试创建新线程非核心线程执行任务直到线程数达到maximumPoolSize。这也是为什么maximumPoolSize必须大于corePoolSize才有意义。 避坑指南序号错误做法正确做法后果1使用Executors创建线程池使用ThreadPoolExecutor手动配置OOM风险2使用无界队列使用有界队列ArrayBlockingQueue任务堆积内存耗尽3忘记处理拒绝策略异常根据业务场景选择合适的拒绝策略任务丢失或不感知4线程池大小拍脑袋配置根据任务类型CPU/IO密集型计算压测资源浪费或性能不足5不自定义threadFactory自定义线程工厂设置有意义的前缀名问题排查困难 可运行验证代码importjava.util.concurrent.*;publicclassThreadPoolDemo{publicstaticvoidmain(String[]args){// ✅ 正确通过 ThreadPoolExecutor 手动创建使用有界队列ThreadPoolExecutorexecutornewThreadPoolExecutor(2,// corePoolSize2个正式员工5,// maximumPoolSize最多5个人60L,// keepAliveTime空闲60秒TimeUnit.SECONDS,// unitnewArrayBlockingQueue(3),// workQueue有界队列最多3个newCustomThreadFactory(),// threadFactory自定义线程工厂newThreadPoolExecutor.CallerRunsPolicy()// handler拒绝策略);// 模拟提交10个任务for(inti1;i10;i){finalinttaskIdi;executor.execute(()-{System.out.println(Thread.currentThread().getName() 执行任务 taskId);try{Thread.sleep(1000);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}});}executor.shutdown();}// ✅ 自定义线程工厂给线程起个有意义的名字方便排查问题staticclassCustomThreadFactoryimplementsThreadFactory{privatefinalAtomicIntegercounternewAtomicInteger(0);OverridepublicThreadnewThread(Runnabler){returnnewThread(r,my-pool-counter.incrementAndGet());}}}❌ 错误示例禁止使用// ❌ 永远不要这样写ExecutorServiceexecutorExecutors.newFixedThreadPool(10);// 问题使用无界 LinkedBlockingQueue任务积压会 OOM❓ 评论区挑战问题以下关于线程池的说法哪一个是错误的// 场景创建线程池ThreadPoolExecutorexecutornewThreadPoolExecutor(2,5,60L,TimeUnit.SECONDS,newArrayBlockingQueue(10),Executors.defaultThreadFactory(),newThreadPoolExecutor.AbortPolicy());A. 当有3个任务同时提交时会创建3个核心线程执行B. 当核心线程全忙且队列已满时会创建非核心线程C. 队列满了且线程数达到5时新任务会被拒绝D.Executors.newFixedThreadPool(10)和手动创建corePoolSize10的ThreadPoolExecutor效果完全一样 欢迎在评论区写出你的答案和理由我会在下一篇文章发布后更新本文公布答案及错误选项逐项解析。✅ 答案公布正确答案A. 当有3个任务同时提交时会创建3个核心线程执行解析corePoolSize2所以最多只能创建2个核心线程。有3个任务同时提交时第1个任务 → 创建核心线程1执行第2个任务 → 创建核心线程2执行第3个任务 →核心线程已满22进入队列等待选项B正确队列满后创建非核心线程最多到5选项C正确队列满且线程数5时触发拒绝策略选项D错误Executors.newFixedThreadPool(10)使用无界LinkedBlockingQueue有OOM风险手动创建应使用有界队列错误选项逐项解析B队列满后创建非核心线程正确。队列满且线程数maximumPoolSize时创建非核心线程。C队列满且线程数5时拒绝正确。此时AbortPolicy抛出异常。D两者效果完全一样错误。Executors默认使用无界队列有OOM风险两者并不一样。 总结维度关键点7大核心参数corePoolSize / maximumPoolSize / keepAliveTime / unit / workQueue / threadFactory / handler4步执行流程核心线程→任务队列→非核心线程→拒绝策略工作队列推荐有界队列ArrayBlockingQueue避免OOM拒绝策略AbortPolicy默认/ CallerRunsPolicy / DiscardPolicy / DiscardOldestPolicy生产铁律禁用Executors使用ThreadPoolExecutor手动配置线程数配置CPU密集型 CPU核心数1IO密集型 2×CPU核心数面试官最看重的三个点7大参数完整列表能准确说出所有参数及其含义4步执行流程能画出“核心线程→队列→非核心线程→拒绝策略”的流程图Executors的坑能说出为什么禁用Executors并举出OOM的例子 系列导航上一篇面试官问volatile和Atomic类的底层原理下一篇预告面试官问死锁的产生条件与排查方法待发布全部85题目录点击查看关注专栏每周2-3篇一键追更搭配学习效果更佳本篇图解帮你快速建立知识画面记忆如果想深入理解源码实现和实战避坑细节可以配合姊妹系列《Java 100天进阶之路》对应章节一起学从零基础到上岗就业108篇完整学习地图每篇标配生活类比 可运行代码 避坑表 面试高频题 练习题不背八股文真正讲透“为什么”。 《Java 100天进阶之路》完整目录导航学习建议图解系列负责“快速建立知识图谱”进阶系列负责“深入理解原理”两个系列搭配使用面试备考效率翻倍。你在实际项目中用过线程池吗有没有遇到过因为使用了Executors导致OOM的线上事故欢迎评论区分享你的故事
面试官问:线程池的核心参数与执行流程?一张图+餐厅运营比喻,彻底拿下这道必考题(附图解+比喻+避坑指南)
面试官问线程池的核心参数与执行流程一张图餐厅运营比喻彻底拿下这道必考题附图解比喻避坑指南预计阅读14分钟 你是不是也这样能说出corePoolSize、maximumPoolSize几个参数名但面试官一追问“corePoolSize和maximumPoolSize什么关系”“Executors有什么坑”“队列满了怎么办”就答不上来了今天一张图 一个餐厅运营故事 源码级解析 六道追问彻底拿下这道题。摘要线程池是Java并发编程的核心工具基于生产者-消费者模型实现线程复用。ThreadPoolExecutor有7大核心参数corePoolSize常驻核心线程、maximumPoolSize最大线程数、keepAliveTime空闲存活时间、unit时间单位、workQueue任务队列、threadFactory线程工厂、handler拒绝策略。任务执行遵循4步流程核心线程→任务队列→非核心线程→拒绝策略。生产环境禁止使用Executors创建线程池必须通过ThreadPoolExecutor手动配置避免OOM风险。一句话核心线程是“常驻员工”非核心线程是“临时工”任务队列是“待办清单”拒绝策略是“最后防线”。我是折哥《Java 85题图解版》系列连载中已更新37题建议收藏本系列。每周2-3篇85题通关路线一键追完。点击关注第一时间收到每篇新题推送。上一篇面试官问volatile和Atomic类的底层原理下一篇预告面试官问死锁的产生条件与排查方法待发布全部85题点击查看总目录关注专栏追更不迷路一句话总结核心线程是“常驻员工”非核心线程是“临时工”任务队列是“待办清单”拒绝策略是“最后防线”。corePoolSize核心线程数正式员工雷打不动即使没活干也留着 → 像餐厅的正式厨师无论有没有客人都在。workQueue工作队列排队等候区 → 像餐厅的等候区客人来了厨师都在忙就先在等候区坐下排队。maximumPoolSize最大线程数正式兼职的总数 → 像等候区坐满了餐厅叫兼职厨师来帮忙但总人数不能超过这个数。keepAliveTime空闲存活时间兼职的下班时间 → 像高峰期过了兼职厨师如果30分钟没事干就让他们走人正式员工继续留着。handler拒绝策略客流超限的应急预案 → 像客人太多正式兼职全忙等候区也满了拒绝策略决定怎么办。背诵口诀核心线程常驻岗任务队列来缓冲非核心线程临时忙拒绝策略最后挡。核心设计理念线程池 生产者-消费者模型——提交任务的线程是生产者池中的工作线程是消费者任务队列是缓冲区。 面试还原面试官你们项目里用线程池吗核心参数怎么配置的任务进来之后是怎么执行的这是Java并发面试中必问必考的核心题直接进入正题。 一图看懂线程池7大参数与4步流程 生活比喻餐厅运营场景设定你是一家餐厅线程池的老板负责接待顾客任务。corePoolSize 正式员工你雇了3名正式厨师corePoolSize3他们是你的核心团队。即使没有客人空闲状态这3个人也照常上班你不会开除他们。任务队列workQueue 排队等候区客人来了3个厨师都在忙新客人就在等候区任务队列坐下排队。等候区有10个座位有界队列坐满了就不能再进来了。maximumPoolSize 正式员工 临时工等候区坐满了还有客人来。你叫来2名兼职厨师非核心线程帮忙现在总共5个人在干活maximumPoolSize5。注意兼职厨师和正式厨师总人数不能超过5人maximumPoolSize是包括核心线程在内的总数。keepAliveTime 临时工的下班时间高峰期过了客人少了。兼职厨师如果30分钟keepAliveTime没事干就让他们下班。正式员工继续留着。拒绝策略handler 客人太多怎么办正式员工3人兼职2人全在忙等候区10个座位全满又来客人了怎么办你的应对方案拒绝策略决定怎么处理方案AAbortPolicy直接拒之门外说“今天不接待了”抛异常方案BCallerRunsPolicy让老板自己下厨做调用者线程执行方案CDiscardPolicy当没看见客人走了就算了静默丢弃方案DDiscardOldestPolicy把等候区最早来的客人请走让新客人进来丢弃最老任务一句话对照核心线程正式员工雷打不动非核心线程兼职忙时来闲时走任务队列等候区排队缓冲拒绝策略客流超限应急预案。 7大核心参数详解面试速查版完整构造方法publicThreadPoolExecutor(intcorePoolSize,// 核心线程数intmaximumPoolSize,// 最大线程数longkeepAliveTime,// 空闲存活时间TimeUnitunit,// 时间单位BlockingQueueRunnableworkQueue,// 工作队列ThreadFactorythreadFactory,// 线程工厂RejectedExecutionHandlerhandler// 拒绝策略){/* ... */}各参数详解参数含义关键点面试考点corePoolSize核心线程数常驻线程默认一直存活核心线程是“正式员工”maximumPoolSize最大线程数核心非核心的总上限非核心线程是“临时工”keepAliveTime空闲存活时间非核心线程空闲超时被回收可设置allowCoreThreadTimeOut(true)让核心线程也超时unit时间单位TimeUnit.SECONDS等—workQueue工作队列存放等待任务的阻塞队列有界队列防止OOMthreadFactory线程工厂创建线程可自定义名称/优先级建议自定义方便问题排查handler拒绝策略队列满且线程达上限时触发4种策略需区分 4种工作队列对比队列类型是否无界特点适用场景风险ArrayBlockingQueue❌ 有界数组实现FIFO任务量可控队列容量需合理设置LinkedBlockingQueue⚠️ 默认无界链表实现FIFO吞吐量要求高Executors默认用这个可能OOMSynchronousQueue❌ 不存储直接交给线程无缓存短任务、高并发需配合大maximumPoolSizePriorityBlockingQueue✅ 无界支持优先级排序任务有优先级需求无界可能OOMDelayQueue✅ 无界延迟执行定时任务/超时处理无界可能OOM 4种拒绝策略详解当线程池已满线程数达maximumPoolSize且队列已满或已关闭时触发。策略行为适用场景风险AbortPolicy默认抛出RejectedExecutionException关键任务必须被感知异常需妥善处理CallerRunsPolicy由提交任务的线程自己执行不允许丢任务的场景可能阻塞提交线程DiscardPolicy静默丢弃新任务非关键日志/监控数据任务丢失不可感知DiscardOldestPolicy丢弃队列中最老的任务再提交新任务可接受丢弃旧任务旧任务可能丢失️ 为什么禁止使用Executors生产铁律⭐很多面试者会用Executors.newFixedThreadPool()创建线程池但这是生产环境的致命陷阱。Executors的三大坑线程池类型潜在风险原因newFixedThreadPool()OOM风险使用无界LinkedBlockingQueue队列长度Integer.MAX_VALUE任务积压耗尽内存newSingleThreadExecutor()OOM风险同上无界队列newCachedThreadPool()OOM风险maximumPoolSize Integer.MAX_VALUE可创建无限线程耗尽内存阿里巴巴Java开发手册明确规定线程池不允许使用Executors创建必须通过ThreadPoolExecutor手动配置。 高频面试追问6道大厂真题追问1corePoolSize和maximumPoolSize有什么区别回答要点核心线程是常驻的非核心线程是动态的。详细回答corePoolSize是核心线程数这些线程会一直存活即使空闲也不会被销毁。maximumPoolSize是最大线程数是核心线程和非核心线程的总和。当任务量超过核心线程队列容量时线程池会创建非核心线程临时工来应对但这些线程空闲超过keepAliveTime后会被回收。追问2线程池的任务执行流程是怎样的最高频回答要点四步走——核心线程→任务队列→非核心线程→拒绝策略。详细回答① 当前线程数 corePoolSize→ 新建核心线程执行任务② 核心线程已满 → 任务进入workQueue排队等待③ 队列已满 → 当前线程数 maximumPoolSize→ 新建非核心线程执行任务④ 队列已满且线程数达maximumPoolSize→ 触发拒绝策略。追问3execute()和submit()有什么区别回答要点submit()可获取返回值execute()无返回值。详细回答execute()是Executor接口定义的方法提交Runnable任务无返回值。submit()是ExecutorService接口定义的方法可提交Runnable或Callable任务返回Future对象可通过Future.get()获取执行结果或异常。追问4如何合理设置线程池大小回答要点分CPU密集型和IO密集型计算。详细回答CPU密集型计算为主corePoolSize CPU核心数 1IO密集型网络/磁盘IO为主corePoolSize 2 × CPU核心数最佳实践通过压测确定观察吞吐量和响应时间找到最优配置混合型任务考虑分层设计——主线程池处理IO型任务子线程池处理计算型任务追问5核心线程会被回收吗回答要点默认不会但可通过参数开启。详细回答默认情况下核心线程不会被回收即使空闲也会一直存活。但可以通过allowCoreThreadTimeOut(true)开启核心线程超时回收此时核心线程空闲超过keepAliveTime后也会被销毁。追问6workQueue满了但线程数还没到maximumPoolSize会创建新线程吗回答要点会。队列满→创建非核心线程。详细回答会。workQueue.offer()返回false队列已满时线程池会尝试创建新线程非核心线程执行任务直到线程数达到maximumPoolSize。这也是为什么maximumPoolSize必须大于corePoolSize才有意义。 避坑指南序号错误做法正确做法后果1使用Executors创建线程池使用ThreadPoolExecutor手动配置OOM风险2使用无界队列使用有界队列ArrayBlockingQueue任务堆积内存耗尽3忘记处理拒绝策略异常根据业务场景选择合适的拒绝策略任务丢失或不感知4线程池大小拍脑袋配置根据任务类型CPU/IO密集型计算压测资源浪费或性能不足5不自定义threadFactory自定义线程工厂设置有意义的前缀名问题排查困难 可运行验证代码importjava.util.concurrent.*;publicclassThreadPoolDemo{publicstaticvoidmain(String[]args){// ✅ 正确通过 ThreadPoolExecutor 手动创建使用有界队列ThreadPoolExecutorexecutornewThreadPoolExecutor(2,// corePoolSize2个正式员工5,// maximumPoolSize最多5个人60L,// keepAliveTime空闲60秒TimeUnit.SECONDS,// unitnewArrayBlockingQueue(3),// workQueue有界队列最多3个newCustomThreadFactory(),// threadFactory自定义线程工厂newThreadPoolExecutor.CallerRunsPolicy()// handler拒绝策略);// 模拟提交10个任务for(inti1;i10;i){finalinttaskIdi;executor.execute(()-{System.out.println(Thread.currentThread().getName() 执行任务 taskId);try{Thread.sleep(1000);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}});}executor.shutdown();}// ✅ 自定义线程工厂给线程起个有意义的名字方便排查问题staticclassCustomThreadFactoryimplementsThreadFactory{privatefinalAtomicIntegercounternewAtomicInteger(0);OverridepublicThreadnewThread(Runnabler){returnnewThread(r,my-pool-counter.incrementAndGet());}}}❌ 错误示例禁止使用// ❌ 永远不要这样写ExecutorServiceexecutorExecutors.newFixedThreadPool(10);// 问题使用无界 LinkedBlockingQueue任务积压会 OOM❓ 评论区挑战问题以下关于线程池的说法哪一个是错误的// 场景创建线程池ThreadPoolExecutorexecutornewThreadPoolExecutor(2,5,60L,TimeUnit.SECONDS,newArrayBlockingQueue(10),Executors.defaultThreadFactory(),newThreadPoolExecutor.AbortPolicy());A. 当有3个任务同时提交时会创建3个核心线程执行B. 当核心线程全忙且队列已满时会创建非核心线程C. 队列满了且线程数达到5时新任务会被拒绝D.Executors.newFixedThreadPool(10)和手动创建corePoolSize10的ThreadPoolExecutor效果完全一样 欢迎在评论区写出你的答案和理由我会在下一篇文章发布后更新本文公布答案及错误选项逐项解析。✅ 答案公布正确答案A. 当有3个任务同时提交时会创建3个核心线程执行解析corePoolSize2所以最多只能创建2个核心线程。有3个任务同时提交时第1个任务 → 创建核心线程1执行第2个任务 → 创建核心线程2执行第3个任务 →核心线程已满22进入队列等待选项B正确队列满后创建非核心线程最多到5选项C正确队列满且线程数5时触发拒绝策略选项D错误Executors.newFixedThreadPool(10)使用无界LinkedBlockingQueue有OOM风险手动创建应使用有界队列错误选项逐项解析B队列满后创建非核心线程正确。队列满且线程数maximumPoolSize时创建非核心线程。C队列满且线程数5时拒绝正确。此时AbortPolicy抛出异常。D两者效果完全一样错误。Executors默认使用无界队列有OOM风险两者并不一样。 总结维度关键点7大核心参数corePoolSize / maximumPoolSize / keepAliveTime / unit / workQueue / threadFactory / handler4步执行流程核心线程→任务队列→非核心线程→拒绝策略工作队列推荐有界队列ArrayBlockingQueue避免OOM拒绝策略AbortPolicy默认/ CallerRunsPolicy / DiscardPolicy / DiscardOldestPolicy生产铁律禁用Executors使用ThreadPoolExecutor手动配置线程数配置CPU密集型 CPU核心数1IO密集型 2×CPU核心数面试官最看重的三个点7大参数完整列表能准确说出所有参数及其含义4步执行流程能画出“核心线程→队列→非核心线程→拒绝策略”的流程图Executors的坑能说出为什么禁用Executors并举出OOM的例子 系列导航上一篇面试官问volatile和Atomic类的底层原理下一篇预告面试官问死锁的产生条件与排查方法待发布全部85题目录点击查看关注专栏每周2-3篇一键追更搭配学习效果更佳本篇图解帮你快速建立知识画面记忆如果想深入理解源码实现和实战避坑细节可以配合姊妹系列《Java 100天进阶之路》对应章节一起学从零基础到上岗就业108篇完整学习地图每篇标配生活类比 可运行代码 避坑表 面试高频题 练习题不背八股文真正讲透“为什么”。 《Java 100天进阶之路》完整目录导航学习建议图解系列负责“快速建立知识图谱”进阶系列负责“深入理解原理”两个系列搭配使用面试备考效率翻倍。你在实际项目中用过线程池吗有没有遇到过因为使用了Executors导致OOM的线上事故欢迎评论区分享你的故事