【Java 开发日记】什么是线程池?它的工作原理?

【Java 开发日记】什么是线程池?它的工作原理?

目录

一、什么是线程池?

二、线程池的核心工作原理

核心组件

工作流程详解(结合上图)

补充:线程回收

三、Java中的线程池实现 (ThreadPoolExecutor)

核心构造函数

常见的任务队列 (workQueue)

内置的拒绝策略

四、通过 Executors 工具类创建的常见线程池

五、最佳实践与总结


一、什么是线程池?

核心思想: 线程池是一种基于“池化”思想来管理线程的工具。它预先创建好一定数量的线程,放入一个“池子”中,当有任务需要执行时,就从池子中取出一个空闲线程来执行任务,任务执行完毕后,线程并不被销毁,而是返回池中等待执行下一个任务。

为什么需要线程池?

在深入原理之前,我们先想想如果不使用线程池,我们如何处理多任务:

// 原始方式:为每个任务创建一个新线程 for (int i = 0; i < 100; i++) { new Thread(() -> { // 执行任务 System.out.println("执行任务:" + Thread.currentThread().getName()); }).start(); }

这种方式存在几个严重问题:

  1. 资源消耗大:创建和销毁线程是非常消耗CPU和内存的。当任务数量非常多时,频繁地创建和销毁线程会严重影响性能。
  2. 管理困难:无法控制线程的数量,如果并发任务过多,会创建大量线程,导致系统负载过高,甚至崩溃。
  3. 稳定性差:缺乏统一的管理,线程之间的竞争和不可预知的行为会增加系统的不稳定性。

线程池的优势:

  • 降低资源消耗:通过复用已创建的线程,避免了频繁创建和销毁线程的开销。
  • 提高响应速度:当任务到达时,无需等待线程创建就能立即执行。
  • 提高线程的可管理性:线程是稀缺资源,线程池可以统一进行分配、调优和监控。可以控制最大并发数,防止无限制创建线程。
  • 提供更强大的功能:线程池提供了定时执行、定期执行、单线程、并发数控制等功能。

二、线程池的核心工作原理

要理解线程池的工作原理,我们需要深入到它的内部组件和执行流程。其核心模型可以用下图清晰地展示:

下面我们来详细拆解图中的每一步。

核心组件
  1. 核心线程池 (corePoolSize):线程池中常驻的“核心部队”。即使它们处于空闲状态,也不会被销毁(除非设置了allowCoreThreadTimeOut为true)。
  2. 任务队列 (workQueue):一个阻塞队列,用于存放待执行的任务。当核心线程都在忙时,新来的任务会被放在这个队列里排队等候。
  3. 最大线程池 (maximumPoolSize):线程池允许创建的最大线程数量。这是线程池的“扩编上限”。
  4. 非核心线程:当任务队列满了,并且当前线程数小于最大线程数时,线程池会创建新的线程来处理任务。这些线程是“临时工”,空闲一段时间后(由keepAliveTime决定)会被销毁。
  5. 拒绝策略 (RejectedExecutionHandler):当任务队列已满,并且线程数已达到最大值时,线程池会采取一种策略来处理新提交的任务。
工作流程详解(结合上图)
  1. 提交任务
    当一个新任务被提交到线程池时,线程池的处理决策流程开始。
  2. 判断核心线程
    • 如果当前运行的线程数 小于 corePoolSize(核心线程数),那么无论是否有空闲线程,线程池都会立即创建一个新的核心线程来执行这个任务。
    • 如果核心线程数已满,则进入下一步。
  3. 尝试入队
    • 线程池会尝试将任务放入任务队列 (workQueue) 进行排队。
    • 如果任务队列未满,任务成功入队,等待核心线程空闲下来后从队列中取出执行。
    • 如果任务队列已满,则进入下一步。
  4. 判断最大线程
    • 如果任务队列已满,但当前运行的线程数 小于 maximumPoolSize(最大线程数),线程池会创建一个新的非核心线程来立即执行这个任务(注意,它执行的是刚提交的这个新任务,而不是队列里的旧任务)。
    • 如果当前线程数已经达到 maximumPoolSize,则进入下一步。
  5. 执行拒绝策略
    • 当线程池和队列都已经“满负荷”工作时,新提交的任务将被拒绝,线程池会调用RejectedExecutionHandler来处理这个任务。
补充:线程回收

当线程池中的线程数量超过了corePoolSize,并且这些“多余”的非核心线程空闲时间超过了keepAliveTime,它们就会被终止,直到线程数量恢复到corePoolSize的大小。

三、Java中的线程池实现 (ThreadPoolExecutor)

在Java中,线程池的核心类是 java.util.concurrent.ThreadPoolExecutor。我们通常通过Executors工厂类来创建配置好的线程池,但更推荐直接使用ThreadPoolExecutor的构造函数来精细控制参数。

核心构造函数
public ThreadPoolExecutor( int corePoolSize, // 核心线程数 int maximumPoolSize, // 最大线程数 long keepAliveTime, // 非核心线程空闲存活时间 TimeUnit unit, // 存活时间单位 BlockingQueue<Runnable> workQueue, // 任务队列 ThreadFactory threadFactory, // 线程工厂(用于创建线程) RejectedExecutionHandler handler // 拒绝策略 )
常见的任务队列 (workQueue)
  • SynchronousQueue:一个不存储元素的队列。每个插入操作必须等待另一个线程的移除操作。这样,提交的任务不会被排队,而是直接创建新线程或执行拒绝策略。Executors.newCachedThreadPool()使用它。
  • LinkedBlockingQueue:一个基于链表的无界队列(除非构造时指定容量)。如果使用无界队列,那么maximumPoolSize参数就失效了,因为队列永远不会满,所以只会创建corePoolSize个线程。
  • ArrayBlockingQueue:一个基于数组的有界队列。可以有效地防止资源耗尽。
内置的拒绝策略
  • ThreadPoolExecutor.AbortPolicy默认):直接抛出RejectedExecutionException异常。
  • ThreadPoolExecutor.CallerRunsPolicy:由调用者所在线程(比如主线程)来执行该任务。这提供了一种简单的反馈控制机制,可以降低新任务的提交速度。
  • ThreadPoolExecutor.DiscardPolicy:默默丢弃无法处理的任务,不抛异常。
  • ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列中最旧的一个任务,然后尝试重新提交当前任务。

四、通过 Executors 工具类创建的常见线程池

  1. newFixedThreadPool (固定大小线程池)
    • corePoolSize = maximumPoolSize = n
    • workQueue = LinkedBlockingQueue(无界队列)
    • 特点:线程数量固定。适用于为了满足资源管理的需求,需要限制当前线程数量的场景。注意:使用无界队列,如果任务过多,可能导致内存溢出(OOM)。
  2. newCachedThreadPool (可缓存线程池)
    • corePoolSize = 0
    • maximumPoolSize = Integer.MAX_VALUE(几乎是无限的)
    • keepAliveTime = 60秒
    • workQueue = SynchronousQueue
    • 特点:线程数量几乎无限制,空闲线程会被回收。适用于执行很多短期异步任务的小程序,或负载较轻的服务器。注意:最大线程数非常大,可能创建大量线程,导致CPU和内存耗尽。
  3. newSingleThreadExecutor (单线程线程池)
    • corePoolSize = maximumPoolSize = 1
    • workQueue = LinkedBlockingQueue(无界队列)
    • 特点:只有一个线程工作。适用于需要保证任务顺序执行,并且在任意时间点不会有多个线程活动的场景。
  4. newScheduledThreadPool (定时任务线程池)
    • 用于在给定的延迟后运行任务,或者定期执行任务。

五、最佳实践与总结

  • 理解参数:根据任务的特性(CPU密集型、IO密集型)合理设置corePoolSizemaximumPoolSizeworkQueue
    • CPU密集型:线程数 ≈ CPU核数 + 1
    • IO密集型:线程数可以设置得多一些,如 2 * CPU核数
  • 推荐手动创建:避免使用Executors的便捷方法,而是直接使用ThreadPoolExecutor构造函数,这样可以更明确线程池的运行规则,规避资源耗尽的风险。
  • 给线程池命名:通过自定义ThreadFactory,为线程设置有意义的名字,便于出错时回溯。
  • 合理选择拒绝策略:根据业务重要性选择合适的拒绝策略。

总结一下:线程池是一个“生产者-消费者”模型的优雅实现。生产者提交任务(Runnable对象),消费者(池中的线程)从任务队列中获取并执行任务。通过预先创建和复用线程,以及对线程数量的管理,它极大地提升了多线程程序的性能、稳定性和可管理性。理解其核心工作原理是编写高效、健壮并发程序的关键。

如果小假的内容对你有帮助,请点赞评论收藏。创作不易,大家的支持就是我坚持下去的动力!

Read more

【Java 基础编程】Java 常用类速查:包装类、String/StringBuilder、Math、日期类一篇搞定

【Java 基础编程】Java 常用类速查:包装类、String/StringBuilder、Math、日期类一篇搞定

常用类是 Java 开发中频繁使用的工具类,掌握这些类的使用方法和特点能够提高开发效率,编写更加规范的代码。 ⚡ 快速参考 * 包装类:将基本类型封装成对象,支持自动装箱和拆箱 * String 类:不可变字符串,使用 + 拼接会创建新对象 * StringBuffer:可变字符串,线程安全,适合多线程环境 * StringBuilder:可变字符串,线程不安全,性能更高,推荐使用 * Math 类:提供数学运算的静态方法 * 日期类:Date、Calendar、LocalDateTime(Java 8+) 📚 学习目标 1. 理解包装类的概念和自动装箱拆箱机制 2. 掌握 String 类的常用方法和不可变性 3. 理解 String、StringBuffer、StringBuilder 的区别 4. 掌握 Math 类的常用方法 5.

By Ne0inhk
飞算JavaAI的安装及其使用方法

飞算JavaAI的安装及其使用方法

标签#JavaAI 首先,我i们先去电脑端自带的浏览器下载IDEA 界面往下滑可以看到下载安装。 安装后软件会显示在桌面,如果没有安装在桌面快捷,可以在系统应用中查找。 启动IDEA,在顶部菜单栏进入 File -> Settings (Windows/Linux)或 IntelliJ IDEA -> Preferences (macOS),打开对话框。 在设置界面左侧选择 Plugins 选项,切换到插件市场。在顶部的搜索框中输入关键词“飞算”。 搜索”Calex-JavaAI“,将该插件安装到右侧使用栏。 在对话框内输入你想要生成代码的题目。这里我用”校园餐饮服务评价系统的设计与实现”为例,做出以下分析及实操过程。 一、需求分析与规划 (一)功能需求 此次开发的餐饮电商系统,对于用户而言,需要能够快速注册登录,维护个人信息,根据自身权限浏览、搜索菜品,下单支付,对已完成订单进行评价等操作;

By Ne0inhk
JAVA IO流:从基础原理到实战应用

JAVA IO流:从基础原理到实战应用

JAVA IO流:从基础原理到实战应用 1.1 本章学习目标与重点 💡 掌握IO流的核心概念与分类,理解字节流与字符流的区别和适用场景。 💡 熟练使用字节流完成文件的读取与写入操作,解决文件拷贝等实际问题。 💡 掌握字符流的使用方法,处理文本文件的编码与解码问题。 💡 了解缓冲流、转换流、对象流等高级IO流的原理,提升IO操作效率。 ⚠️ 本章重点是 字节流与字符流的核心用法 和 高级IO流的实战应用,这是JAVA文件操作的必备技能。 1.2 IO流核心概念与分类 1.2.1 什么是IO流 💡 IO流(Input/Output Stream)是JAVA中用于处理设备之间数据传输的技术,主要负责数据的读取(Input)和写入(Output)。 常见的IO操作包括文件读写、网络通信数据传输等。IO流的核心思想是以流的方式处理数据,数据像水流一样从一个设备流向另一个设备,实现数据的传输与处理。 1.2.2 IO流的分类标准 JAVA中的IO流体系庞大,可按照不同标准进行分类,核心分类方式有以下三种: 1.

By Ne0inhk
Flutter 三方库 algolia_client_recommend 的鸿蒙化适配指南 - 打造 AI 驱动的个性化推荐引擎、助力鸿蒙端电商与内容应用转化率倍增

Flutter 三方库 algolia_client_recommend 的鸿蒙化适配指南 - 打造 AI 驱动的个性化推荐引擎、助力鸿蒙端电商与内容应用转化率倍增

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 algolia_client_recommend 的鸿蒙化适配指南 - 打造 AI 驱动的个性化推荐引擎、助力鸿蒙端电商与内容应用转化率倍增 前言 在 OpenHarmony 鸿蒙应用全场景连接的商业版图中,“信息找人”已成为提升流量价值的核心逻辑。无论是电商应用的“经常一起购买”,还是内容平台的“相关推荐”,高质量的个性化算法能显著降低用户的决策成本。algolia_client_recommend 作为一个连接 Algolia 顶尖 AI 推荐服务的专业客户端,为开发者提供了一套开箱即用的推荐逻辑封装。本文将详述如何在鸿蒙端利用此库构建“读懂用户”的智能化交互。 一、原原理分析 / 概念介绍 1.1 基础原理 algolia_client_recommend 的核心逻辑是 基于意图建模的异步推荐查询与联合过滤机制

By Ne0inhk