Wrayの知识库 Wrayの知识库
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
  • Java章节编写规范
  • Java基础

  • Java集合

  • Java并发

    • Java并发概述
    • 线程与进程
    • Thread类与线程生命周期
    • 线程创建与任务模型
    • 线程安全
    • synchronized关键字
    • volatile关键字
    • Java内存模型(JMM)
    • 线程间通信
    • 线程池
      • 1. 为什么需要线程池
      • 2. 核心参数
      • 3. 执行流程
      • 4. 工作队列
      • 5. 拒绝策略
      • 6. 线程工厂
      • 7. 不推荐 Executors 快捷方法
      • 8. 线程数估算
      • 9. 关闭线程池
      • 10. 异常处理
      • 11. 常见配置模板
      • Tips 快问快答
    • 并发工具类
    • 原子操作类Atomic
    • 并发锁
    • 并发容器
    • ConcurrentHashMap
    • BlockingQueue
    • CopyOnWriteArrayList
    • ThreadLocal
    • Fork/Join框架
    • ScheduledThreadPoolExecutor
    • CompletableFuture
    • 虚拟线程
    • 死锁活锁与线程问题排查
    • 并发编程最佳实践
  • Java IO

  • JVM

  • Java
  • Java并发
Wray
2026-06-24
目录

线程池

线程池用于管理和复用线程,是 Java 服务端并发编程的核心工具。它能限制线程数量、复用工作线程、缓冲任务、统一处理拒绝和关闭。

生产系统中,几乎不应该为每个请求直接 new Thread。

# 1. 为什么需要线程池

线程池解决:

问题 说明
创建销毁成本 复用线程,减少频繁创建
资源失控 限制线程数量,保护系统
任务排队 用队列缓冲短时峰值
统一治理 命名、监控、拒绝、关闭
异步执行 主流程快速返回,任务后台执行

模型:

提交任务
  │
  ▼
ThreadPoolExecutor
  │
  ├─ 工作线程
  ├─ 任务队列
  ├─ 线程工厂
  └─ 拒绝策略

# 2. 核心参数

new ThreadPoolExecutor(
        corePoolSize,
        maximumPoolSize,
        keepAliveTime,
        unit,
        workQueue,
        threadFactory,
        rejectedExecutionHandler
);
参数 含义
corePoolSize 核心线程数
maximumPoolSize 最大线程数
keepAliveTime 非核心线程空闲存活时间
workQueue 任务队列
threadFactory 创建线程
handler 拒绝策略

# 3. 执行流程

execute(task)
  │
  ├─ 当前线程数 < corePoolSize
  │    └─ 新建核心线程执行
  │
  ├─ 否则尝试入队
  │    └─ 入队成功,等待执行
  │
  ├─ 队列满且线程数 < maximumPoolSize
  │    └─ 新建非核心线程执行
  │
  └─ 仍无法处理
       └─ 执行拒绝策略

关键点:如果队列是无界队列,任务会一直入队,maximumPoolSize 可能永远用不上。

# 4. 工作队列

队列 特点 风险
ArrayBlockingQueue 有界数组队列 需要指定容量
LinkedBlockingQueue 链表队列,可有界 默认容量很大,要显式设置
SynchronousQueue 不存储任务,直接交接 容易创建大量线程
PriorityBlockingQueue 优先级队列 无界风险,顺序由比较器决定
DelayQueue 延迟队列 适合定时/延迟任务

生产环境优先使用有界队列,避免任务无限堆积导致 OOM。

# 5. 拒绝策略

策略 行为
AbortPolicy 抛 RejectedExecutionException
CallerRunsPolicy 调用者线程执行任务
DiscardPolicy 静默丢弃新任务
DiscardOldestPolicy 丢弃队列最老任务,再尝试提交

推荐:

  • 默认可以用 AbortPolicy,让问题暴露。
  • 限流削峰可考虑 CallerRunsPolicy,让提交方变慢。
  • 不要随意使用静默丢弃,除非业务允许。

# 6. 线程工厂

线程池必须命名。

ThreadFactory factory = new ThreadFactory() {
    private final AtomicInteger index = new AtomicInteger();

    @Override
    public Thread newThread(Runnable r) {
        Thread thread = new Thread(r);
        thread.setName("order-worker-" + index.incrementAndGet());
        thread.setUncaughtExceptionHandler((t, e) -> log.error("线程异常: {}", t.getName(), e));
        return thread;
    }
};

线程名能直接提升排查效率。

# 7. 不推荐 Executors 快捷方法

Executors 很方便,但隐藏了队列和线程数风险:

方法 风险
newFixedThreadPool 默认无界队列,任务可能堆积
newSingleThreadExecutor 默认无界队列
newCachedThreadPool 最大线程数很大,可能创建过多线程
newScheduledThreadPool 延迟队列任务堆积风险

生产代码推荐显式创建 ThreadPoolExecutor,写清线程数、队列容量和拒绝策略。

# 8. 线程数估算

CPU 密集型:

线程数 ≈ CPU 核心数 或 核心数 + 1

IO 密集型:

线程数 ≈ CPU 核心数 * (1 + 等待时间 / 计算时间)

这只是估算,最终要压测。

观察指标:

  • 活跃线程数。
  • 队列长度。
  • 拒绝次数。
  • 任务耗时。
  • CPU 使用率。
  • 下游连接池使用率。

# 9. 关闭线程池

优雅关闭:

executor.shutdown();
if (!executor.awaitTermination(30, TimeUnit.SECONDS)) {
    executor.shutdownNow();
}

区别:

方法 行为
shutdown 不接收新任务,继续执行队列任务
shutdownNow 尝试中断正在执行任务,返回未执行任务

任务要响应中断,否则 shutdownNow 也不能保证立即停止。

# 10. 异常处理

execute 中异常会抛给线程异常处理器。submit 中异常会封装到 Future。

Future<?> future = executor.submit(() -> {
    throw new RuntimeException("error");
});

future.get(); // 才能观察到异常

建议:

  • 任务内部记录关键异常。
  • 对 Future 结果做消费。
  • 使用 afterExecute 统一处理。
  • 监控线程池拒绝和异常。

# 11. 常见配置模板

ThreadPoolExecutor executor = new ThreadPoolExecutor(
        8,
        16,
        60,
        TimeUnit.SECONDS,
        new ArrayBlockingQueue<>(1000),
        factory,
        new ThreadPoolExecutor.CallerRunsPolicy()
);

这不是万能参数,只是说明生产线程池应有边界。

# Tips 快问快答

Q:线程池核心参数有哪些? A:核心线程数、最大线程数、存活时间、队列、线程工厂、拒绝策略。

Q:线程池提交任务流程是什么? A:先建核心线程,再入队,队列满再建非核心线程,最后拒绝。

Q:为什么不推荐 Executors? A:它隐藏无界队列或过大线程数风险。

Q:maximumPoolSize 什么时候生效? A:队列满且当前线程数小于最大线程数时。

Q:生产线程池为什么要有界队列? A:防止任务无限堆积导致内存溢出。

Q:CallerRunsPolicy 有什么效果? A:由提交线程执行任务,能对上游形成反压。

Q:线程池怎么优雅关闭? A:先 shutdown,等待超时后必要时 shutdownNow。

Q:submit 的异常去哪了? A:封装在 Future 中,调用 get 时抛出。

上次更新: 2026/06/24, 17:22:59
线程间通信
并发工具类

← 线程间通信 并发工具类→

Copyright © 2023-2026 Wray | 鄂ICP备2024050235号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式