应慎用executors.newfixedthreadpool,因其使用无界linkedblockingqueue易致oom,生产环境须手动构建threadpoolexecutor,显式配置有界队列、拒绝策略及命名线程工厂。

使用 Executors.newFixedThreadPool 构建固定大小线程池时,核心在于明确线程数与并发变量总量的协同控制逻辑——线程池大小决定并行执行上限,而并发变量(如共享计数器、缓存、连接池等)需配合同步机制或无锁设计,避免因线程争用导致状态错乱或资源耗尽。
合理设定线程池大小:匹配任务类型与系统资源
固定线程池的大小不是越大越好,需结合任务性质权衡:
-
CPU 密集型任务:线程数建议设为
Runtime.getRuntime().availableProcessors()或略高(如 +1),避免过多线程上下文切换拖慢整体性能; - I/O 密集型任务(如 HTTP 调用、数据库查询):可适当放大,例如设为 CPU 核数的 2–4 倍,让等待 I/O 的线程不阻塞其他计算;
-
混合型任务:优先按实际压测结果调整,而非理论公式。例如:
ExecutorService pool = Executors.newFixedThreadPool(8);
控制并发变量总量:避免共享状态竞争
当多个线程共用同一变量(如全局计数器、Map 缓存、数据库连接)时,必须主动管控其并发访问方式:
- 用
AtomicInteger/AtomicLong替代普通int/long,保证计数类操作原子性; - 对集合类变量,优先选用线程安全实现,如
ConcurrentHashMap、CopyOnWriteArrayList,而非加synchronized锁整个方法; - 若必须用非线程安全对象(如
SimpleDateFormat),改用ThreadLocal隔离实例,避免复用引发格式错乱; - 涉及外部资源(如数据库连接、文件句柄),应通过连接池(如 HikariCP)统一管理总量,而非依赖线程池大小间接控制。
配合生命周期管理:防止资源泄漏与线程滞留
固定线程池不会自动关闭,需在业务结束时显式调用关闭流程:
- 调用
shutdown()停止接收新任务,等待已有任务完成; - 必要时调用
awaitTermination(long timeout, TimeUnit unit)设置最大等待时间; - 若需强制终止,再调用
shutdownNow()(注意:正在运行的任务可能被中断,需确保任务本身支持响应中断); - 典型模式:务必在 finally 块或 try-with-resources(配合自定义 CloseableExecutor)中执行 shutdown,避免 JVM 退出前线程池仍在运行。
替代方案提醒:newFixedThreadPool 的隐含风险
该工厂方法创建的线程池使用无界队列(LinkedBlockingQueue),当任务提交速度远超处理速度时,会导致队列无限堆积、内存溢出:
- 生产环境更推荐手动构造
ThreadPoolExecutor,指定有界队列(如ArrayBlockingQueue)并配置拒绝策略(如AbortPolicy、CallerRunsPolicy); - 示例:
new ThreadPoolExecutor(4, 4, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue(100), new ThreadPoolExecutor.CallerRunsPolicy()); - 这样既能控线程数,又能控待处理任务总量,真正实现“并发变量总量”双维度约束。










