当前位置: 首页 > 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.dtcms.com/a/319311.html

相关文章:

  • Mac 电脑安装 ADB 环境完整指南
  • 流程图使用规范
  • Git Status 命令深度指南:洞悉仓库状态的核心艺术
  • 专题二_滑动窗口_长度最小的子数组
  • 进程Linux
  • 打靶日记-PHPinclude-labs(一)
  • 攻防世界WEB(新手模式)2-2-upload1
  • MySQL中的DDL(一)
  • 深入理解动态规划算法
  • 数字孪生系统让汽车工厂虚实联动预测维护少停机
  • LabVIEW注册表操作
  • 图像认知与OpenCV——图像预处理4
  • python opencv 调用 海康威视工业相机(又全又细又简洁)
  • Java开发时出现的问题---架构与工程实践缺陷
  • KUKA库卡焊接机器人氩气节气设备
  • Nuclei漏洞扫描工具(除了常见漏洞还支持CMS常见漏洞Gitlab、Jira、Splunk、Elastic)
  • 解决Git提交人信息默认全局化问题:让提交人自动关联当前用户
  • sklearn study notes[3]
  • Kong vs. NGINX:从反向代理到云原生网关的全景对比
  • 从零开始学习:深度学习(基础入门版)(1天)
  • [激光原理与应用-168]:测量仪器 - 对光学指标进行测量的仪器
  • 从“数字网格”到“空中交警” :星图低空云如何重构低空管理?
  • 嵌入式第二十二课!!!链式队列与哈希表
  • Maven分模块开发实战指南
  • Qt 子类重新实现父类的槽函数
  • 「iOS」————持久化
  • 【0基础3ds Max】菜单栏介绍
  • 【分享】我国八大沙漠空间矢量范围
  • Bonree ONE发布直通车 | 可观测平台如何深度应用LLM技术
  • 如何科学选择光伏运维系统?