当前位置: 首页 > news >正文

线程池创建线程

文章目录

      • 1. 可扩展线程池(`newCachedThreadPool`)
      • 2. 固定线程池(`newFixedThreadPool`)
      • 3. 单一线程池(`newSingleThreadExecutor`)
      • 4. 延时周期线程池(`newScheduledThreadPool`)
        • 1)特殊情况处理:
        • 2)与 `scheduleWithFixedDelay` 的区别:
      • 5. 自定义线程池(`ThreadPoolExecutor`)
        • 1)`AbortPolicy`(默认策略)
        • 2) `CallerRunsPolicy`
        • 3) `DiscardPolicy`
        • 4) `DiscardOldestPolicy`
        • 5)拒绝策略选择建议
        • 6)参数配置原则
      • 6.核心区别对比表
      • 7.注意事项

Java 中常见的线程池类型包括可扩展线程池、固定线程池、单一线程池、延时周期线程池以及自定义线程池,它们各自有不同的特性和适用场景,具体区别如下:

1. 可扩展线程池(newCachedThreadPool

  • 核心特性
    • 线程数量动态变化,没有核心线程,最大线程数为 Integer.MAX_VALUE(理论上可无限扩展)
    • 空闲线程超过60秒会自动销毁,避免资源浪费
    • 使用 SynchronousQueue 作为任务队列(不存储任务,直接传递给线程)
  • 适用场景
    • 短期任务多、任务执行时间短的场景(如网络请求处理)
    • 不需要控制线程数量上限的场景
  • 示例
    ExecutorService cachedPool = Executors.newCachedThreadPool();
    

2. 固定线程池(newFixedThreadPool

  • 核心特性
    • 线程数量固定(创建时指定,核心线程数 = 最大线程数)
    • 线程不会自动销毁,即使空闲也会保留
    • 使用 LinkedBlockingQueue 作为任务队列(无界队列,可存储大量等待任务)
  • 适用场景
    • 任务数量稳定、执行时间较长的场景(如后台计算)
    • 需要控制并发线程数,避免资源耗尽的场景
  • 示例
    ExecutorService fixedPool = Executors.newFixedThreadPool(5); // 固定5个线程
    

3. 单一线程池(newSingleThreadExecutor

  • 核心特性
    • 仅包含1个核心线程,所有任务按顺序执行
    • 任务队列使用 LinkedBlockingQueue(无界队列)
    • 线程意外终止时会自动创建新线程替代,保证始终有1个线程执行任务
  • 适用场景
    • 需要任务按顺序执行的场景(如日志写入、单线程事务处理)
    • 避免并发处理导致的数据不一致问题
  • 示例
    ExecutorService singlePool = Executors.newSingleThreadExecutor();
    

4. 延时周期线程池(newScheduledThreadPool

  • 核心特性
    • 可延迟执行任务或按周期重复执行任务
    • 核心线程数固定,最大线程数为 Integer.MAX_VALUE
    • 使用 DelayedWorkQueue 作为任务队列(按延迟时间排序)
  • 适用场景
    • 定时任务(如定时备份、定时检查)
    • 周期性任务(如每隔1小时执行一次统计)
  • 示例
    ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(3);
    // 延迟2秒执行任务
    scheduledPool.schedule(() -> System.out.println("延迟执行"), 2, TimeUnit.SECONDS);
    // 延迟1秒后,每3秒执行一次任务
    scheduledPool.scheduleAtFixedRate(() -> System.out.println("周期执行"), 1, 3, TimeUnit.SECONDS);
    
1)特殊情况处理:
  1. 任务执行时间 > 周期

    • 下一次执行会在当前任务结束后立即开始(不会并行执行)
    • 示例:若任务耗时4秒,周期3秒,则实际间隔为4秒
  2. 任务被中断

    • 若任务执行中被中断,后续周期执行会被取消
  3. 线程池关闭

    • 调用 shutdown() 后,已提交的周期任务会继续执行,直到所有任务完成或被中断
2)与 scheduleWithFixedDelay 的区别:
  • scheduleAtFixedRate:以上一次开始时间计算下一次执行时间(固定频率)
  • scheduleWithFixedDelay:以上一次结束时间计算下一次执行时间(固定延迟)

例如同样是3秒周期,任务耗时2秒:

  • scheduleAtFixedRate:实际间隔为3秒(1→4→7秒执行)
  • scheduleWithFixedDelay:实际间隔为3+2=5秒(1→6→11秒执行)

5. 自定义线程池(ThreadPoolExecutor

  • 核心特性
    • 通过 ThreadPoolExecutor 构造函数手动配置所有参数,灵活度最高
    • 可自定义核心线程数、最大线程数、空闲线程存活时间、任务队列、拒绝策略等
  • 核心参数
    new ThreadPoolExecutor(corePoolSize,       // 核心线程数(始终保留的线程数)maximumPoolSize,    // 最大线程数(允许的最大线程数)keepAliveTime,      // 非核心线程空闲超时时间unit,               // 超时时间单位workQueue,          // 任务队列(存储等待执行的任务)threadFactory,      // 线程工厂(自定义线程名称、优先级等)handler             // 拒绝策略(任务过多时的处理方式)
    );
    
  • 适用场景
    • 对线程池有精细控制需求的场景(如自定义任务队列大小、拒绝策略)
    • 复杂业务场景(如需要限制任务队列长度,避免内存溢出)
  • 示例
    // 自定义线程池:核心2个,最大5个,队列长度10,拒绝策略为丢弃任务并记录日志
    ThreadPoolExecutor customPool = new ThreadPoolExecutor(2, 5, 60, TimeUnit.SECONDS,new ArrayBlockingQueue<>(10),Executors.defaultThreadFactory(),new ThreadPoolExecutor.DiscardPolicy()
    );
    

ThreadPoolExecutor 是 Java 中最核心的线程池实现类,通过灵活配置参数可满足不同场景需求。以下是其核心参数解释及四种内置拒绝策略的详细说明:

1)AbortPolicy(默认策略)
  • 行为:直接抛出 RejectedExecutionException 异常,阻止系统正常运行
  • 适用场景:需要明确知道任务被拒绝的场景,便于及时处理
new ThreadPoolExecutor.AbortPolicy()
2) CallerRunsPolicy
  • 行为:让提交任务的线程(调用者线程)亲自执行该任务
  • 效果:减缓新任务提交速度,给线程池缓冲时间,避免任务丢失
  • 适用场景:并发量不大、任务不紧急的场景
new ThreadPoolExecutor.CallerRunsPolicy()
3) DiscardPolicy
  • 行为:直接丢弃新提交的任务,不抛出异常,也不做任何处理
  • 风险:任务丢失,且无法感知
  • 适用场景:任务无关紧要,允许丢失的场景(如日志收集)
new ThreadPoolExecutor.DiscardPolicy()
4) DiscardOldestPolicy
  • 行为:丢弃等待队列中最旧的任务(队列头部任务),然后尝试提交新任务
  • 适用场景:需要处理最新任务,旧任务可被替代的场景
new ThreadPoolExecutor.DiscardOldestPolicy()
5)拒绝策略选择建议
  1. 生产环境中不建议使用默认的 AbortPolicy,可能导致业务中断
  2. 对任务安全性要求高 → 选择 CallerRunsPolicy(至少尝试执行)
  3. 允许任务丢失但需最新任务 → 选择 DiscardOldestPolicy
  4. 非核心任务(如统计、日志)→ 可选择 DiscardPolicy
  5. 复杂场景可自定义拒绝策略(实现 RejectedExecutionHandler 接口),例如:
    // 自定义策略:记录被拒绝的任务,后续手动处理
    RejectedExecutionHandler customHandler = (r, executor) -> {log.error("任务被拒绝: {}", r.toString());// 可将任务存入数据库或消息队列
    };
    
6)参数配置原则
  • 核心线程数:根据 CPU 核心数或业务并发量设置(如 CPU 密集型任务 = CPU 核心数 + 1)
  • 最大线程数:避免过大(防止资源耗尽),通常为核心线程数的 2~4 倍
  • 等待队列:建议使用有界队列(如 ArrayBlockingQueue),避免无界队列导致 OOM
  • 拒绝策略:结合业务对任务丢失的容忍度选择,优先保证核心任务执行

6.核心区别对比表

线程池类型核心线程数最大线程数任务队列类型适用场景特点总结
可扩展线程池0Integer.MAX_VALUESynchronousQueue短期、快速任务动态扩缩容,自动销毁空闲线程
固定线程池nnLinkedBlockingQueue任务数量稳定、耗时较长线程数量固定,复用性好
单一线程池11LinkedBlockingQueue顺序执行任务串行执行,保证任务顺序
延时周期线程池nInteger.MAX_VALUEDelayedWorkQueue定时/周期性任务支持延迟和周期执行
自定义线程池自定义自定义自定义(如ArrayBlockingQueue)复杂场景,需精细控制灵活配置所有参数

7.注意事项

  1. 所有线程池使用后必须调用 shutdown()shutdownNow() 关闭,避免资源泄漏。
  • 但是在延时周期任务中scheduledAtFixedRate(),添加了pool.shutdown()方法后,线程池会拒绝接收新任务。
  1. Executors 提供的默认线程池可能存在隐患(如 newFixedThreadPool 使用无界队列可能导致OOM),复杂场景建议使用自定义线程池
  2. 选择线程池时需根据任务特性(执行时间、数量、并发需求)合理配置参数
http://www.lryc.cn/news/613548.html

相关文章:

  • jmeter要如何做接口测试?
  • Jmeter使用第一节-认识面板(Mac版)
  • 【线性代数】5特征值和特征向量
  • Vue3获取当前页面相对路径
  • 站在Vue的角度,对比鸿蒙开发中的状态管理
  • Casrel关系抽取
  • vue3 el-select 加载触发
  • AI绘画:生成唐初李世民全身像提示词
  • 【unity实战】使用Unity程序化生成3D随机地牢(附项目源码)
  • 8.3.1 注册服务中心Etcd
  • 【感知机】感知机(perceptron)学习算法的对偶形式
  • Java包装类详解与应用指南
  • Caffeine 三种过期策略详解
  • Day 6: CNN卷积神经网络 - 计算机视觉的核心引擎
  • MCU中的USB
  • 论文解读:单个标点符号如何欺骗LLM,攻破AI评判系统
  • Linux总线,设备和驱动关系以及匹配机制解析
  • vue打包号的文件如何快速查找文件打包后的位置
  • Redis 编译错误:缺少静态库文件,如何解决?
  • 在NVIDIA Orin上用TensorRT对YOLO12进行多路加速并行推理时内存泄漏 (中)
  • PoE延长器——突破网络距离限制
  • 数据赋能(386)——数据挖掘——迭代过程
  • PyCharm 图标 c、m、f、F、v、p 的含义
  • 科技云报到:热链路革命:阿卡 CRM 的 GTM 定位突围
  • 健永科技工位RFID读卡器实现生产流水线物料跟踪与柔性化升级
  • 美食广场: 城市胃的便利店
  • MySQL UNION 操作符详细说明
  • 如何在GPU上安装使用Docker
  • SupChains团队:订单生产型供应链销量预测建模案例分享(六)
  • 容器之王--Docker的部署及基本操作演练