优先选 ArrayBlockingQueue,因其有界性可暴露容量瓶颈并配合拒绝策略保障稳定;若用 LinkedBlockingQueue 必须显式指定容量,禁用无界构造。

线程池创建时用 LinkedBlockingQueue 还是 ArrayBlockingQueue?
取决于任务提交频率和可控性。LinkedBlockingQueue 默认无界,看似安全,但容易掩盖背压问题——当生产者(提交任务)远快于消费者(线程执行),队列无限增长,最终触发 OutOfMemoryError。ArrayBlockingQueue 是有界队列,能强制暴露容量瓶颈,配合合理的拒绝策略更利于系统稳定。
- 高吞吐、任务执行时间短且可预测 → 选
ArrayBlockingQueue,设合理容量(如核心线程数 × 2~4) - 任务来源不可控、需容忍短时突发 → 可用
LinkedBlockingQueue,但必须显式指定容量(如new LinkedBlockingQueue(1000)),绝不用无参构造 - 若用
SynchronousQueue,它不存储任务,仅作“手递手”中转,适合 CPU 密集型、希望立即触发线程创建的场景,但会频繁启停线程,慎用于 I/O 密集型
ThreadPoolExecutor 的 corePoolSize 和 maximumPoolSize 怎么设?
这不是调优起点,而是业务负载建模的结果。盲目设大值会导致线程争抢 CPU 或阻塞在 I/O 上,反而降低吞吐;设太小则任务积压、响应延迟升高。
- CPU 密集型任务:理论上限 ≈
Runtime.getRuntime().availableProcessors(),corePoolSize和maximumPoolSize可设为相同值,避免线程上下文切换开销 - I/O 密集型任务(如 HTTP 调用、DB 查询):需估算平均 I/O 等待时间占比,公式参考:
corePoolSize ≈ CPU 核数 / (1 - 阻塞系数),其中阻塞系数常取 0.8~0.9,即单线程约 80% 时间在等 I/O - 永远不要把
maximumPoolSize设为Integer.MAX_VALUE—— 这会让线程池在队列满后无限制新建线程,极大概率 OOM
为什么 submit(Runnable) 返回的 Future 调用 get() 会阻塞?
因为 Future.get() 是同步等待语义,它会挂起当前线程直到任务完成或超时。这不是 bug,而是设计使然。但在线程池内部调用它,极易造成死锁——比如所有工作线程都在等另一个任务的 get(),而那个任务又排在队列里,无人执行。
- 避免在
Runnable或Callable内部调用同一线程池中其他任务的future.get() - 如需组合多个异步结果,优先用
CompletableFuture.supplyAsync(..., executor)配合thenCombine/allOf,它们不阻塞线程,而是注册回调 - 若必须阻塞等待,确保调用方不在该线程池的工作线程中(例如放在 Servlet 线程或独立的调度线程里)
关闭线程池时,shutdown() 和 shutdownNow() 的实际行为差异
shutdown() 是温和终止:不再接受新任务,但会等所有已提交任务(包括队列中未执行的)完成;shutdownNow() 是强制中断:尝试停止正在执行的任务(通过 Thread.interrupt()),并清空队列、返回未执行任务列表。
请注意以下说明:1、本程序允许任何人免费使用。2、本程序采用PHP+MYSQL架构编写。并且经过ZEND加密,所以运行环境需要有ZEND引擎支持。3、需要售后服务的,请与本作者联系,联系方式见下方。4、本程序还可以与您的网站想整合,可以实现用户在线服务功能,可以让客户管理自己的信息,可以查询自己的订单状况。以及返点信息等相关客户利益的信息。这个功能可提高客户的向心度。安装方法:1、解压本系统,放在
立即学习“Java免费学习笔记(深入)”;
- 绝大多数场景应优先用
shutdown()+awaitTermination(long, TimeUnit),给任务留出合理收尾时间(如释放连接、刷盘日志) -
shutdownNow()仅适用于可中断任务(即代码中检查了Thread.currentThread().isInterrupted()并主动退出),否则中断信号被忽略,任务仍会跑完 - Spring 中用
@PreDestroy关闭线程池时,务必加超时等待逻辑,否则应用可能假死在关闭阶段
executor.shutdown();
try {
if (!executor.awaitTermination(30, TimeUnit.SECONDS)) {
executor.shutdownNow();
if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
System.err.println("线程池未正常关闭");
}
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}真正难的不是选哪个队列或设几个线程,而是理解每个参数背后对资源竞争、任务生命周期和错误传播路径的影响。多数线上问题,都出在“以为设了线程池就等于并发安全”,却没管住任务本身的阻塞点和依赖关系。










