一、线程池概述

1、线程池的优势
  • 线程池是一种线程使用模式,线程过多会带来调度开销,进而影响缓存局部性和整体性能,而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务,这避免了在处理短时间任务时创建与销毁线程的代价,线程池不仅能够保证内核的充分利用,还能防止过分调度

  • 线程池的工作主要是控制运行的线程数量,在处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量,超出数量的线程排队等候,等其他线程执行完毕,再从队列中取出任务来执行

2、线程池的特点
  • 降低资源消耗: 通过重复利用已创建的线程降低线程创建和销毁造成的销耗

  • 提高响应速度: 当任务到达时,任务可以不需要等待线程创建就能立即执行

  • 提高线程的可管理性: 线程是稀缺资源,如果无限制的创建,不仅会销耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控


二、线程池的架构

  • Java 中的线程池是通过 Executor 框架实现的,该框架中用到了 Executor 接口,Executors 类,ExecutorService 类,ThreadPoolExecutor 类

三、线程池的种类与创建

1、一池 N 线程
(1)基本介绍
  • 线程池中的线程处于一定的量,可以很好的控制线程的并发量

  • 线程可以重复被使用,在显示关闭之前,都将一直存在

  • 超出一定量的线程被提交时候需在队列中等待

(2)创建方式
ExecutorService threadPool = Executors.newFixedThreadPool(5);
(3)适用场景
  • 适用于可以预测线程数量的业务,或者服务器负载较重,对线程数有严格限制的场景
(4)基本使用
  • 使用 5 个窗口处理 10 个顾客请求
ExecutorService threadPool = Executors.newFixedThreadPool(5);try {for (int i = 1; i <= 10; i++) {// 执行线程threadPool.execute(() -> {System.out.println(Thread.currentThread().getName()+" 办理业务");});}
} catch (Exception e) {e.printStackTrace();
} finally {// 关闭线程threadPool.shutdown();
}
  • 结果
pool-1-thread-1 办理业务
pool-1-thread-5 办理业务
pool-1-thread-4 办理业务
pool-1-thread-3 办理业务
pool-1-thread-2 办理业务
pool-1-thread-3 办理业务
pool-1-thread-4 办理业务
pool-1-thread-5 办理业务
pool-1-thread-1 办理业务
pool-1-thread-2 办理业务
2、一池一线程
(1)基本介绍
  • 线程池中最多执行一个线程,之后提交的线程活动将会排在队列中依次执行
(2)创建方式
ExecutorService threadPool = Executors.newSingleThreadExecutor();
(3)适用场景
  • 适用于需要保证顺序执行各个任务,并且在任意时间点,不会同时有多个线程的场景
(4)基本使用
  • 使用 1 个窗口处理 10 个顾客请求
ExecutorService threadPool = Executors.newSingleThreadExecutor();try {for (int i = 1; i <= 10; i++) {// 执行线程threadPool.execute(() -> {System.out.println(Thread.currentThread().getName()+" 办理业务");});}
} catch (Exception e) {e.printStackTrace();
} finally {// 关闭线程threadPool.shutdown();
}
  • 结果
pool-1-thread-1 办理业务
pool-1-thread-1 办理业务
pool-1-thread-1 办理业务
pool-1-thread-1 办理业务
pool-1-thread-1 办理业务
pool-1-thread-1 办理业务
pool-1-thread-1 办理业务
pool-1-thread-1 办理业务
pool-1-thread-1 办理业务
pool-1-thread-1 办理业务
3、一池可扩容线程
(1)基本介绍
  • 线程池中数量没有固定,可达到最大值为 Interger. MAX_VALUE

  • 线程池中的线程可进行缓存重复利用和回收,默认回收时间为一分钟

  • 当线程池中没有可用线程时,会重新创建一个线程

(2)创建方式
ExecutorService threadPool = Executors.newCachedThreadPool();
(3)适用场景
  • 适用于创建一个可无限扩大的线程池,服务器负载压力较轻,执行时间较短,任务多的场景
(4)基本使用
  • 处理 20 个顾客请求
ExecutorService threadPool = Executors.newCachedThreadPool();try {for (int i = 1; i <= 20; i++) {// 执行线程threadPool.execute(() -> {System.out.println(Thread.currentThread().getName()+" 办理业务");});}
} catch (Exception e) {e.printStackTrace();
} finally {// 关闭线程threadPool.shutdown();
}
  • 结果
pool-1-thread-1 办理业务
pool-1-thread-4 办理业务
pool-1-thread-3 办理业务
pool-1-thread-2 办理业务
pool-1-thread-6 办理业务
pool-1-thread-5 办理业务
pool-1-thread-8 办理业务
pool-1-thread-7 办理业务
pool-1-thread-3 办理业务
pool-1-thread-4 办理业务
pool-1-thread-7 办理业务
pool-1-thread-5 办理业务
pool-1-thread-1 办理业务
pool-1-thread-2 办理业务
pool-1-thread-6 办理业务
pool-1-thread-8 办理业务
pool-1-thread-3 办理业务
pool-1-thread-9 办理业务
pool-1-thread-7 办理业务
pool-1-thread-5 办理业务

四、线程池的底层原理

1、ThreadPoolExecutor 类
  • 通过查看上面三种方式创建线程池对象的源代码,发现都有 new ThreadPoolExecutor 操作,具体查看该类的源代码,其构造器涉及七个参数
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {if (corePoolSize < 0 ||maximumPoolSize <= 0 ||maximumPoolSize < corePoolSize ||keepAliveTime < 0)throw new IllegalArgumentException();if (workQueue == null || threadFactory == null || handler == null)throw new NullPointerException();this.acc = System.getSecurityManager() == null ?null :AccessController.getContext();this.corePoolSize = corePoolSize;this.maximumPoolSize = maximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler;
}
2、ThreadPoolExecutor 构造器涉及的七个参数
  1. int corePoolSize:常驻线程数量

  2. int maximumPoolSize:最大线程数量

  3. long keepAliveTime:空闲线程存活时间

  4. TimeUnit unit:空闲线程存时间单位

  5. BlockingQueue workQueue:阻塞队列,存放提交但未执行任务

  6. ThreadFactory threadFactory:线程工厂,用于创建线程(可省略)

  7. RejectedExecutionHandler handler:阻塞队列满时的拒绝策略(可省略)


五、线程池的工作流程

  • 在创建了线程池后,线程池中的线程数为零

  • 当调用 execute 方法添加一个请求任务时,线程池会做如下判断

    1. 如果正在运行的线程数量小于 corePool 的线程数量,那么马上创建线程运行这个任务

    2. 如果正在运行的线程数量大于或等于 corePool 的线程数量,那么将这个任务存入阻塞队列

    3. 如果这个时候队列已满且正在运行的线程数量小于 maximumPool 的线程数量,则创建非核心线程立刻运行这个任务

    4. 如果队列已满且正在运行的线程数量大于或等于 maximumPool 的线程数量,那么线程池会启动拒绝策略

  • 当一个线程完成任务时,它会从队列中取下一个任务来执行

  • 当一个线程空闲超过一定的时间时,会做如下判断

    1. 如果当前运行的线程数大于 corePool 的线程数量,那么这个线程就被停掉

    2. 线程池的所有任务完成后,最终会收缩到 corePool 的大小


六、线程池的拒绝策略

1、 AbortPolicy
  • 默认的拒绝策略,会直接抛出 RejectedExecutionException 异常阻止系统正常运行
2、DiscardPolicy
  • 该策略会丢弃无法处理的任务,不给予任何处理也不抛出异常,如果允许任务丢失,这是最好的一种策略
3、DiscardOldestPolicy
  • 丢弃队列中等待最久的任务,然后把当前任务存入队列中,并尝试提交当前任务
4、CallerRunsPolicy
  • 该策略既不会丢弃任务,也不会抛出异常,而是将任务退回给调用者

七、自定义线程池

1、Executors 返回的线程池对象的弊端
  • FixedThreadPool 和 SingleThreadExecutor 允许请求队列的长度为 Interger.MAX_VALUE,可能会堆积大量异常, 从而导致 OOM

  • CachedThreadPool 允许的创建线程数量为 Interger.MAX_VALUE,可能会创建大量线程,从而导致 OOM

2、具体实现
package com.my.pool;import java.util.concurrent.*;public class MyThreadPoolTest {public static void main(String[] args) {ExecutorService threadPool = new ThreadPoolExecutor(2,5,2L,TimeUnit.SECONDS,new ArrayBlockingQueue<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.DiscardOldestPolicy());// 处理 10 个顾客请求try {for (int i = 1; i <= 10; i++) {// 执行线程threadPool.execute(() -> {System.out.println(Thread.currentThread().getName()+" 办理业务");});}} catch (Exception e) {e.printStackTrace();} finally {// 关闭线程threadPool.shutdown();}}
}
  • 结果
pool-1-thread-1 办理业务
pool-1-thread-4 办理业务
pool-1-thread-3 办理业务
pool-1-thread-2 办理业务
pool-1-thread-3 办理业务
pool-1-thread-4 办理业务
pool-1-thread-1 办理业务
pool-1-thread-5 办理业务

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/76798.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/76798.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/76798.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

驱动开发硬核特训 · Day 6 : 深入解析设备模型的数据流与匹配机制 —— 以 i.MX8M 与树莓派为例的实战对比

&#x1f50d; B站相应的视屏教程&#xff1a; &#x1f4cc; 内核&#xff1a;博文视频 - 从静态绑定驱动模型到现代设备模型 主题&#xff1a;深入解析设备模型的数据流与匹配机制 —— 以 i.MX8M 与树莓派为例的实战对比 在上一节中&#xff0c;我们从驱动框架的历史演进出…

Blender安装基础使用教程

本博客记录安装Blender和基础使用&#xff0c;可以按如下操作来绘制标靶场景、道路标识牌等。 目录 1.安装Blender 2.创建面板资源 步骤 1: 设置 Blender 场景 步骤 2: 创建一个平面 步骤 3: 将 PDF 转换为图像 步骤 4-方法1: 添加材质并贴图 步骤4-方法2&#xff1a;创…

智能手机功耗测试

随着智能手机发展,用户体验对手机的续航功耗要求越来越高。需要对手机进行功耗测试及分解优化,将手机的性能与功耗平衡。低功耗技术推动了手机的用户体验。手机功耗测试可以采用powermonitor或者NI仪表在功耗版上进行测试与优化。作为一个多功能的智能终端,手机的功耗组成极…

从代码学习深度学习 - 多头注意力 PyTorch 版

文章目录 前言一、多头注意力机制介绍1.1 工作原理1.2 优势1.3 代码实现概述二、代码解析2.1 导入依赖序列掩码函数2.2 掩码 Softmax 函数2.3 缩放点积注意力2.4 张量转换函数2.5 多头注意力模块2.6 测试代码总结前言 在深度学习领域,注意力机制(Attention Mechanism)是自然…

学术版 GPT 网页

学术版 GPT 网页 1. 学术版 GPT 网页非盈利版References https://academic.chatwithpaper.org/ 1. 学术版 GPT 网页非盈利版 arXiv 全文翻译&#xff0c;免费且无需登录。 更换模型 System prompt: Serve me as a writing and programming assistant. 界面外观 References …

MarkDown 输出表格的方法

MarkDown用来输出表格很简单&#xff0c;比Word手搓表格简单多了&#xff0c;而且方便修改。 MarkDown代码&#xff1a; |A|B|C|D| |:-|-:|:-:|-| |1|b|c|d| |2|b|c|d| |3|b|c|d| |4|b|c|d| |5|b|c|d|显示效果&#xff1a; ABCD1bcd2bcd3bcd4bcd5bcd A列强制左对齐&#xf…

MetaGPT深度解析:重塑AI协作开发的智能体框架实践指南

一、框架架构与技术突破 1.1 系统架构设计 graph TBA[自然语言需求] --> B(需求解析引擎)B --> C{角色路由系统}C --> D[产品经理Agent]C --> E[架构师Agent]C --> F[工程师Agent]D --> G[PRD文档]E --> H[架构图]F --> I[代码文件]G --> J[知识共…

自用:在使用SpringBoot做学生信息管理系统时遇到的问题

1、在做完查询测试时&#xff0c;一直报出404找不到错误&#xff0c;原因是没有为各个层的实现类添加注解 2、改完之后发现测试没有数据&#xff0c;是因为我写的返回值类型为空&#xff0c;应该返回一个List< Student > 3、我没有想到要写Result实体类&#xff0c;因为不…

SQLite + Redis = Redka

Redka 是一个基于 SQLite 实现的 Redis 替代产品&#xff0c;实现了 Redis 的核心功能&#xff0c;并且完全兼容 Redis API。它可以用于轻量级缓存、嵌入式系统、快速原型开发以及需要事务 ACID 特性的键值操作等场景。 功能特性 Redka 的主要特点包括&#xff1a; 使用 SQLi…

202529 | RocketMQ 简介 + 安装 + 集群搭建 + 消费模式 + 消费者组

RocketMQ简介 RocketMQ 简介 Apache RocketMQ 是一款开源的 分布式消息中间件&#xff08;Message Queue, MQ&#xff09;&#xff0c;由阿里巴巴团队研发并捐赠给 Apache 基金会&#xff0c;现已成为顶级项目。它专为 高吞吐、低延迟、高可靠 的分布式场景设计&#xff0c;广…

Go语言--语法基础4--基本数据类型--整数类型

整型是所有编程语言里最基础的数据类型。 Go 语言支持如下所示的这些整型类型。 需要注意的是&#xff0c; int 和 int32 在 Go 语言里被认为是两种不同的类型&#xff0c;编译器也不会帮你自动做类型转换&#xff0c; 比如以下的例子会有编译错误&#xff1a; var value2 in…

竞拍商城:电商创新的博弈场与未来趋势

竞拍商城&#xff1a;电商创新的博弈场与未来趋势 在传统电商趋于同质化的今天&#xff0c;竞拍商城凭借其独特的交易机制和用户激励模式&#xff0c;成为电商领域的新宠。通过结合拍卖的博弈属性与电商的便捷性&#xff0c;竞拍商城不仅重塑了消费体验&#xff0c;更催生了全…

Linux : 多线程互斥

目录 一 前言 二 线程互斥 三 Mutex互斥量 1. 定义一个锁&#xff08;造锁&#xff09; 2. 初始化锁 3. 上锁 4. 解锁 5. 摧毁锁 四 锁的使用 五 锁的宏初始化 六 锁的原理 1.如何看待锁&#xff1f; 2. 如何理解加锁和解锁的本质 七 c封装互斥锁 八 可重入…

论文阅读笔记——Reactive Diffusion Policy

RDP 论文 通过 AR 提供实时触觉/力反馈&#xff1b;慢速扩散策略&#xff0c;用于预测低频潜在空间中的高层动作分块&#xff1b;快速非对称分词器实现闭环反馈控制。 ACT、 π 0 \pi_0 π0​ 采取了动作分块&#xff0c;在动作分块执行期间处于开环状态&#xff0c;无法及时响…

swagger 注释说明

一、接口注释核心字段 在 Go 的路由处理函数&#xff08;Handler&#xff09;上方添加注释&#xff0c;支持以下常用注解&#xff1a; 注解名称用途说明示例格式Summary接口简要描述Summary 创建用户Description接口详细说明Description 通过用户名和邮箱创建新用户Tags接口分…

STM32 HAL库 OLED驱动实现

一、概述 1.1 OLED 显示屏简介 OLED&#xff08;Organic Light - Emitting Diode&#xff09;即有机发光二极管&#xff0c;与传统的 LCD 显示屏相比&#xff0c;OLED 具有自发光、视角广、响应速度快、对比度高、功耗低等优点。在嵌入式系统中&#xff0c;OLED 显示屏常被用…

Web开发-JavaEE应用动态接口代理原生反序列化危险Invoke重写方法利用链

知识点&#xff1a; 1、安全开发-JavaEE-动态代理&序列化&反序列化 2、安全开发-JavaEE-readObject&toString方法 一、演示案例-WEB开发-JavaEE-动态代理 动态代理 代理模式Java当中最常用的设计模式之一。其特征是代理类与委托类有同样的接口&#xff0c;代理类…

K8s是常用命令和解释

K8s高频命令 获取资源信息&#xff0c;如获取 Pod、Service、Deployment等资源状态信息 kubectl get创建资源如创建Pod、Service、Deployment等资源 kubectl create删除资源&#xff0c;如删除Pod、Service、Deployment等资源 kubectl delete 应用配置文件&#xff0c;如引用D…

【模态分解】EMD-经验模态分解

算法配置页面&#xff0c;也可以一键导出结果数据 报表自定义绘制 获取和下载【PHM学习软件PHM源码】的方式 获取方式&#xff1a;Docshttps://jcn362s9p4t8.feishu.cn/wiki/A0NXwPxY3ie1cGkOy08cru6vnvc

TDengine 语言连接器(Go)

简介 driver-go 是 TDengine 的官方 Go 语言连接器&#xff0c;实现了 Go 语言 database/sql 包的接口。Go 开发人员可以通过它开发存取 TDengine 集群数据的应用软件。 Go 版本兼容性 支持 Go 1.14 及以上版本。 支持的平台 原生连接支持的平台和 TDengine 客户端驱动支持…