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

多线程基础系列-线程池

文章目录

  • 多线程基础系列-线程池
    • 1. 何为线程池?
    • 2. 为什么要使用线程池?
    • 3. 线程池的工作原理
      • 3.1 线程池的几个关键参数
      • 3.2 线程池的工作原理
    • 4. Java中的线程池实现
      • 4.1 Executor 框架
      • 4.2 线程池的创建方式
      • 4.3 线程池的选择
      • 4.3 有必要提一提`ThreadPoolTaskExecutor`

多线程基础系列-线程池

多线程编程是提升程序的性能和响应速度的重要手段,是我们开发人员手中的一把利器。本文将深入探讨线程池的相关知识,包括其基本概念、工作原理、优势以及在Java中的实现方式,帮助读者更好地理解和运用线程池。

1. 何为线程池?

线程池是一种线程使用模式,它维护了一个可复用的线程集合。当有任务需要执行时,线程池会从池中取出一个空闲线程来执行该任务,任务执行完毕后,线程并不会立即销毁,而是返回线程池中等待下一次被复用。这种模式可以有效减少线程创建和销毁的开销,提高程序的执行效率。

换句话,以前我们执行任务需要手动创建线程,以及做一些复杂的线程管控,现在我们只需要从一个池中拿一个线程来执行我们的任务便可

2. 为什么要使用线程池?

  1. 减少开销:避免频繁创建和销毁线程带来的资源消耗。
  2. 提高响应速度:复用已有线程快速响应任务请求。
  3. 合理利用资源:根据系统资源和任务特性合理控制线程数量,防止资源耗尽或闲置。
  4. 便于管理监控:方便对线程进行统一管理,监控线程状态和任务执行情况,便于调优和排查问题。

3. 线程池的工作原理

3.1 线程池的几个关键参数

  • corePoolSize:核心线程数
    线程池中常驻的核心线程数量。即使线程空闲,这部分线程也会保留在线程池中,不会被回收。只有在工作队列满并且当前线程数小于最大线程数时才会创建新的线程。

  • maximumPoolSize:最大线程数
    线程池能容纳的最大线程数量。当活动线程达到这个数值后,新来的任务如果不能放入任务队列将被拒绝处理。

  • keepAliveTime:空闲线程存活时间
    当线程池中的线程数量超过核心线程数时,多余的空闲线程在等待新任务最长时间达到keepAliveTime后,如果还没有新任务到来,那么这些线程将被终止以节省资源。

  • workQueue:任务队列
    用于保存等待执行的任务的阻塞队列。不同的队列实现会影响线程池的行为,常见的有ArrayBlockingQueue(固定大小)、LinkedBlockingQueue(无界或有限界限)、SynchronousQueue(直接传递,没有容量)等。

  • handler:拒绝策略
    当线程池和任务队列都达到饱和状态时(即无法再接受新任务),如何处理新提交的任务。JDK内置了几种拒绝策略:

AbortPolicy:默认策略,丢弃任务并抛出RejectedExecutionException异常。
CallerRunsPolicy:调用者运行策略,直接在调用者线程中执行被拒绝的任务。
DiscardPolicy:静默丢弃任务,不抛出任何异常。
DiscardOldestPolicy:丢弃队列中最旧的任务,并尝试重新提交当前任务。

3.2 线程池的工作原理

  1. 线程池初始化:根据corePoolSize初始化核心线程。
  2. 任务提交:当任务提交到线程池时,根据当前线程数判断:
    • 若当前线程数小于corePoolSize,创建新的线程执行任务。
    • 若当前线程数大于或等于corePoolSize,任务被加入workQueue队列。
  3. 任务处理:当有空闲线程时,从workQueue中取出任务执行。
  4. 线程扩展:若队列已满且当前线程数小于maximumPoolSize,创建新的线程处理任务。
  5. 线程回收:当线程空闲时间超过keepAliveTime,多余的线程会被回收,直到线程数不超过corePoolSize。
  6. 拒绝策略:若队列已满且当前线程数达到maximumPoolSize,则根据拒绝策略处理新任务。

4. Java中的线程池实现

4.1 Executor 框架

Java提供了java.util.concurrent包来支持线程池的创建和管理。其中,ThreadPoolExecutor类是线程池的核心实现类,它提供了丰富的配置选项和灵活的线程管理功能。

示例代码:

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    2, 4, 60, TimeUnit.SECONDS, 
    new LinkedBlockingQueue<>(10), 
    Executors.defaultThreadFactory(), 
    new ThreadPoolExecutor.AbortPolicy()
);

4.2 线程池的创建方式

线程池的创建方法总共有 7 种,但总体来说可分为 2 类:

  • 通过 ThreadPoolExecutor 创建的线程池
  • 通过 Executors 创建的线程池

线程池的创建方式总共包含以下 7 种(其中 6 种是通过 Executors 创建的,1 种是通过 ThreadPoolExecutor 创建的):

  1. Executors.newFixedThreadPool():创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待;
  2. Executors.newCachedThreadPool():创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收多余的线程,若线程数不够,则新建线程;
  3. Executors.newScheduledThreadPool():创建一个可以执行延迟任务的线程池;
  4. Executors.newSingleThreadExecutor():创建单个线程数的线程池,它可以保证先进先出的执行顺序;
  5. Executors.newSingleThreadScheduledExecutor():创建一个单线程的可以执行延迟任务的线程池;
  6. Executors.newWorkStealingPool():创建一个抢占式执行的线程池(任务执行顺序不确定)JDK 1.8 添加
  7. ThreadPoolExecutor:最原始的创建线程池的方式,它包含了 7 个参数可供设置

单线程池的意义: 虽然 newSingleThreadExecutornewSingleThreadScheduledExecutor 是单线程池,但提供了工作队列,生命周期管理,工作线程维护等功能。

4.3 线程池的选择

我们看看《阿里巴巴Java开发手册终极版》中给我们的建议:

强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样
的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
说明:Executors 返回的线程池对象的弊端如下:
1)FixedThreadPool 和 SingleThreadPool:
允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
2)CachedThreadPool 和 ScheduledThreadPool:
允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。

4.3 有必要提一提ThreadPoolTaskExecutor

ThreadPoolTaskExecutor 是 Spring 框架对 ThreadPoolExecutor 的封装,用于在 Spring 应用中更方便地管理线程池。它继承自 AbstractExecutorService,并提供了与 Spring 集成的便利性。

抱歉刚才的表格格式没有完全符合Markdown规范。以下是完全符合Markdown格式的表格:
markdown复制

特性ThreadPoolExecutorThreadPoolTaskExecutor
语言层面Java 标准库Spring 框架
配置方式手动创建,直接使用构造方法通过 Spring 配置类或 XML 配置
与 Spring 的集成需要手动管理生命周期自动管理生命周期,支持 Spring 生命周期管理
线程池参数提供丰富的配置选项提供类似的配置选项,更易与 Spring 集成
使用场景适用于任何 Java 应用专为 Spring 应用设计,适合与 @Async@Scheduled 集成
底层实现基于 java.util.concurrent基于 ThreadPoolExecutor 封装

相关文章:

  • 洛谷 P8705:[蓝桥杯 2020 省 B1] 填空题之“试题 E :矩阵” ← 卡特兰数
  • 322.零钱兑换
  • Go语言--语法基础2--下载安装
  • AF3 DataPipeline类process_multiseq_fasta 方法解读
  • [数据结构笔记] 1. 顺序表 内含所有函数C语言代码,完全无伪代码
  • 使用串口工具实现tcp与udp收发
  • Leetcode2717:半有序排列
  • 【原创工具】同文件夹PDF文件合并 By怜渠客
  • 安全见闻4
  • 多功能免费网络测速及问题诊断工具
  • 【C++】:STL详解 —— vector类
  • C++知识整理day9——继承(基类与派生类之间的转换、派生类的默认成员函数、多继承问题)
  • Linux(Centos 7.6)命令详解:uniq
  • 【愚公系列】《Python网络爬虫从入门到精通》034-DataFrame简单数据计算整理
  • 表单制作代码,登录动画背景前端模板
  • 2025网络安全等级测评报告,信息安全风险评估报告(Word模板)
  • DeepSeek开源周Day2:DeepEP - 专为 MoE 模型设计的超高效 GPU 通信库
  • win11 24h2 远程桌面 频繁断开 已失去连接 2025
  • 通过Python编程语言实现“机器学习”小项目教程案例
  • Ollama微调
  • 扁平化网站设计方案/全网整合营销推广系统
  • 网站开发需求表/百度识图网页版在线
  • 网站开发技术技巧/开封seo公司
  • web网站百度不收录吗/深圳抖音推广公司
  • 网站备案 取消/广告软文200字
  • wordpress添加tag标签/百度自然排名优化