java进阶—通俗易懂线程池的概念(底层原理)及使用

news2025/1/4 18:32:18

前言

首先,我们知道创建一个线程 可以直接 使用

new  Thread(() ->{}).start();

这种形式来创建,当线程的run 方法执行结束,线程就终止了,线程对象就会被垃圾回收机制(GC)释放

然而在我们 开发工作中,特别是一些大厂,高并发的情况随处可见,就需要很多线程来支撑,在没了解线程池之前,我们创建多个线程是这样的


new  Thread(() ->{}).start();
new  Thread(() ->{}).start();
new  Thread(() ->{}).start();
......

无非就是new多个,你要多少个我给你创造多少个

要知道,在高并发的情况下,这样创建多线程是很消耗性能的,不可取,这就需要对线程进行统一管控,就引入了线程池的概念

线程池是什么

线程池是对多个线程进行统一管理维护,当用户把任务提交给线程池,会先进入线程池的阻塞队列,然后线程池中的多个线程会从线程池中的任务队列获取任务执行

在这里插入图片描述

线程怎么创建

用这个 ThreadPoolExecutor 一定要用这个

不管什么 newFixedThreadPool, newScheduledThreadPool ,newSingleThreadExecutor ,newCachedThreadPool ,其底层都是调用了 ThreadPoolExecutor 的构造方法去构建

为什么不要使用他们?(是一定不要,而不是不建议

这边直接说明原因,他们会 导致OOM

OOM,全称“Out Of Memory”,意思就是“内存耗尽,用完了”,来源于java.lang.OutOfMemoryError。

下面是java官方的介绍

Thrown when the Java Virtual Machine cannot allocate an object because
it is out of memory, and no more memory could be made available by the
garbage collector.
意思就是说,当JVM因为没有足够的内存来为对象分配空间并且垃圾回收器也已经没有空间可回收时,就会抛出这个error(注:非exception,因为这个问题已经严重到不足以被应用处理)。

可见OOM的严重性

然而 ThreadPoolExecutor 很好的 避免了资源耗尽的情况,我们可以根据需求来自定义参数

现在我们来看 使用ThreadPoolExecutor 的创建


 ExecutorService executorService = new ThreadPoolExecutor(3, 5, 1L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3),
                Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

在这里插入图片描述

线程池底层+参数讲解

打开原码,来看看里边的参数

在这里插入图片描述
来看看这里边的参数

  • corePoolSize: 线程池中核心线程的最大数
  • maximumPoolSize:线程池中能拥有的最多线程数
  • keepAliveTime: 线程空闲时间
  • unit: 时间单位
  • workQuenu: 任务队列
  • threadFactory 线程工厂
  • handle 拒绝策略

怎么理解这里边的参数呢?

这边举个营业厅办理业务的 例子

营业厅就是一个线程池,里面的所有柜台就是线程中拥有最多线程数(maximumPoolSize),在服务的柜台就是 线程池的核心线程数(corePoolSize),营业厅等待的座椅就好比 任务队列 (workQuenu)

在线程池中,还有一个概念叫应急线程数 它的数量 你设置的总线程数- 核心线程数

应急线程数是当 队列中的任务排满 ,以及所有线程都在处理任务 的情况下,这时候又来一个任务,线程池就会启动应急线程数,当应急线程数也启用完了,队列也满了,再来一个任务,这时候就会触发拒绝策略,也就是说,我这个线程池已经容不下你了 (这是有界的情况)

无界是这个等待队列会一直增长,除非资源耗尽,不然不存在容不下的情况,来了就去队列里边等 (无界)

在这里插入图片描述
线程空闲时间:线程池会判断已开启应急线程数的空闲时间,如果在设置的时间都是闲着的,就会将这个线程回收,,一般都是60s,一分钟

时间单位:不用说了,就是空闲时间的单位

注意一点:线程池没有什么 我可以站着等,我不坐下来(不进队列),这跟我们生活中办理业务还是有区别的,在线程池中 任务进来就去队列 (当然也不是绝对,别急,马上来解释)

来细说细说任务队列:

在一个线程池中,它的任务队列有以下几种形式

  • 有界任务队列 (ArrayBlockingQuene

有界任务队列,就是我们前面例子创建线程使用的了,使用这个队列的线程池 遵循 先进先出 的规格,也就是说 在当 核心线程数 都 不在空闲状态,进来的任务就进入 队列 ,你先进来,等有线程空闲 你就先执行

  • 无界任务队列 ( linkedBlockingQuene)

这也是先进先出,先来先执行 不同于有界是 这个等待队列,他会自己增长,前边介绍应急线程数也提到了

  • 直接提交队列 (SynchronousQuene)

这个就不一样了,这个队列没有容量,提交给线程池任务不会被线程池缓存,他就是将新的任务给线程执行,要是没有空闲的线程,就尝试创建应急线程,当达到规定最大值,触发拒绝策略

再通俗一点,没有等待队列这个概念

  • 优先任务队列 ( priorityBlockingQuene)

这个就等于有VIP机制,是一个特殊的无界队列,他这个可以根据 任务优先级顺序进行执行

所以,前边说的 ,任务进来并不是绝对进队列的原因就在这

简单使用代码实例

public static void main(String[] args) {

        ExecutorService executorService = new ThreadPoolExecutor(3, 5, 1L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3),
                Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

        for (int i = 0; i <7 ; i++) {
            int finalI = i;
            executorService.execute(() ->{
                System.out.println(Thread.currentThread().getName() + "===>办理"+ finalI +"业务");
            });
        }
        executorService.shutdown();
    }

在这里插入图片描述
Executors.defaultThreadFactory() :默认工厂创建

new ThreadPoolExecutor.AbortPolicy():这是api给出的默认拒绝策略,抛出异常

策略其实也有很多种形式

【以上就是线程池底层原理解析以及简单使用案例了!!】

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

智安网络|攻防演练对抗:网络边界自动化防御的关键

在当今高度互联的数字世界中&#xff0c;网络安全的重要性日益凸显。为了应对不断增长的网络威胁&#xff0c;组织和企业需要采取主动的防御策略&#xff0c;其中攻防演练对抗和自动化防御在保护网络边界方面扮演着重要的角色。本文将探讨攻防演练对抗的意义&#xff0c;并介绍…

四、用户管理

云尚办公系统&#xff1a;用户管理 B站直达【为尚硅谷点赞】: https://www.bilibili.com/video/BV1Ya411S7aT 本博文以课程相关为主发布&#xff0c;并且融入了自己的一些看法以及对学习过程中遇见的问题给出相关的解决方法。一起学习一起进步&#xff01;&#xff01;&#x…

ImportError: numpy.core.multiarray failed to import

遇到的问题&#xff1a; 解决方法&#xff1a; 根据你的opencv版本&#xff0c;去百度搜索对应的 numpy 版本&#xff0c;卸载掉现有的numpy &#xff0c;安装其他版本: sudo pip install numpy1.19.0或者直接升级到numpy的最新版本&#xff1a; sudo pip install --upgrade…

小程序-真机上接口无法调通,开发者工具上可以

近期在对接小程序&#xff0c;在这里记录一下&#xff0c;我们在对接小程序的时候碰到的一些奇奇怪怪的问题。 其中一个问题如下&#xff1a; 真实效果如下图 开发者工具上可以&#xff0c;访问没有人任何问题。 真机上接口无法调通&#xff0c;也没有报错&#xff0c;也没有…

idea中git的使用详细说明

一.克隆项目 1. 打开File>New>Project from Version Control... 2. 打开gitLab&#xff0c;复制项目地址 3. 粘贴到第1步中的URL中&#xff0c;点击“Clone” 二.代码提交 1. 修改文件后需要提交时&#xff0c;可以在git-Local Changes中看到你修改的文件及修改内容 2. 选…

netty学习(1):多个客户端与服务器通信

1. 基于前面一节netty学习&#xff08;1&#xff09;:1个客户端与服务器通信 只需要把服务器的handler改造一下即可&#xff0c;通过ChannelGroup 找到所有的客户端channel&#xff0c;发送消息即可。 package server;import io.netty.channel.*; import io.netty.channel.gr…

MS1826 HDMI 多功能视频处理器 4*4矩阵切换器

基本介绍 MS1826 是一款多功能视频处理器&#xff0c;包含 4 路独立 HDMI 音视频输入通道、4 路独立 HDMI 音视频输出通道以及四路独立可配置为输入或者输出的 SPDIF、I2S 音频信号。支持 4 个独立的字 库定制型 OSD&#xff1b;可处理隔行和逐行视频或者图形输入信号&#xff…

Spring Boot 中的 @ComponentScan 注解是什么,原理,如何使用

Spring Boot 中的 ComponentScan 注解是什么&#xff0c;原理&#xff0c;如何使用 在 Spring Boot 中&#xff0c;ComponentScan 是一种注解&#xff0c;它可以让 Spring 自动扫描指定的包及其子包中的组件&#xff0c;并将这些组件自动装配到 Spring 容器中。本文将介绍 Com…

UML14种图

UML14种图 UML是Unified Modeling Language的缩写&#xff0c;译为统一建模语言。 UML是软件行业的建模规范&#xff0c;可以对软件项目建立需求模型、设计模型、实现模型、测试模型。 UML2.0包含的14种图&#xff1a; UML各种图例&#xff08;常用图形&#xff09; 1. 类图&…

状态机编程实例-状态表法

上篇文章&#xff0c;使用嵌套switch-case法的状态机编程&#xff0c;实现了一个炸弹拆除小游戏。 本篇&#xff0c;继续介绍状态机编程的第二种方法&#xff1a;状态表法&#xff0c;来实现炸弹拆除小游戏的状态机编程。 1 状态表法 状态表法&#xff0c;顾名思义&#xff0…

YOLOv8的目标对象的分类,分割,跟踪和姿态估计的多任务检测实践(Netron模型可视化)

YOLOv8是目前最新版本&#xff0c;在以前YOLO版本基础上建立并加入了一些新的功能&#xff0c;以进一步提高性能和灵活性&#xff0c;是目前最先进的模型。YOLOv8旨在快速&#xff0c;准确&#xff0c;易于使用&#xff0c;使其成为广泛的目标检测和跟踪&#xff0c;实例分割&a…

MATLAB 之 Simulink 操作基础和系统仿真模型的建立

这里写目录标题 一、Simulink 操作基础1. Simulink 的启动与退出1.1 Simulink 的启动1.2 模型文件的打开1.3 Simulink 的退出 2. Simulink 仿真初步2.1 模型元素2.2 仿真步骤2.3 简单实例 二、系统仿真模型的建立1. Simulink 的基本模块2. 模块操作2.1 添加与删除模块2.2 选取模…

快速训练自己的大语言模型:基于LLAMA-7B的lora指令微调

目录 1. 选用工程&#xff1a;lit-llama2. 下载工程3. 安装环境4. 下载LLAMA-7B模型5. 做模型转换6. 初步测试7. 为什么要进行指令微调&#xff1f;8. 开始进行指令微调8.1. 数据准备8.2 开始模型训练8.3 模型测试 前言&#xff1a; 系统&#xff1a;ubuntu 18.04显卡&#xff…

大数据ETL工具对比(Sqoop, DataX, Kettle)

前言 在实习过程中&#xff0c;遇到了数据库迁移项目&#xff0c;对于数据仓库&#xff0c;大数据集成类应用&#xff0c;通常会采用ETL工具辅助完成&#xff0c;公司和客户使用的比较多的是Sqoop, DataX和Kettle这三种工具。简单的对这三种ETL工具进行一次梳理。 ETL工具&…

无法更新iPhone,提示“无法检查更新”怎么办?

当我们需要 iPhone更新系统时&#xff0c;可以前往iPhone设置-通用-软件更新中获取更新推送。不过一些用户可能会遇到无法更新的问题&#xff0c;例如会提示“无法检查更新&#xff0c;检查软件更新时出错”。 以上情况可能是网络问题&#xff0c;可以尝试重新打开设置&#xf…

vue2实现公式规则编辑校验弹窗功能

文章目录 需求描述技术栈最终效果演示功能实现逻辑拆分代码目录结构实现思路光标实现底部单个符号或字段结构设计监听键盘事件&处理光标公式规则校验 总结 需求描述 需要一个弹窗&#xff0c;弹窗内部需要能够进行公式规则的配置并进行公式规则合法性校验。 技术栈 vue2e…

Thymeleaf的常用语法

&#x1f31f; Thymeleaf的常用语法 Thymeleaf是一个Java模板引擎&#xff0c;用于处理HTML、XML、JavaScript、CSS等文件。它可以与Spring框架无缝集成&#xff0c;为Web应用程序提供优雅的模板解决方案。本文将介绍Thymeleaf的常用语法&#xff0c;包括th属性、表达式、内置…

Spring Boot 中的 @RestController 注解,如何使用

Spring Boot 中的 RestController 注解 在 Spring Boot 中&#xff0c;我们经常需要编写 RESTful Web 服务&#xff0c;以便于客户端与服务器之间的通信。为了简化 RESTful Web 服务的开发&#xff0c;Spring Boot 提供了 RestController 注解&#xff0c;它可以让我们更方便地…

Jmeter实现参数加密

目录 一、使用__digest自带函数 以md5加密算法演示使用方法 二、在BeanShell 中使用JAVA代码实现算法加密 规避BUG的方法 JMeter有两种方法可以实现算法加密 一、使用__digest自带函数 参数说明&#xff1a; Digest algorithm&#xff1a;算法摘要&#xff0c;可输入值&a…

如何避免在处理数据时出现错误?

介绍 当业务运营管道中发生大量事情时&#xff0c;数据输入任务的优先级往往较低。但是&#xff0c;数据输入被认为是所有行业部门中经常发生的最重要的任务之一。从销售数据到客户分析&#xff0c;从财务数据到库存管理&#xff0c;每项工作都依赖于数据输入&#xff0c;这意…