【JavaEE】——线程池大总结
阿华代码,不是逆风,就是我疯,
你们的点赞收藏是我前进最大的动力!!希望本文内容能够帮助到你!
目录
引入:问题引入
一:解决方案
1:方案一——协程/纤程
(1)本质
2:方案二——线程池
(1)本质
(2)优缺点
(3)解释高效的原因
二:ThreadPoolExecutor(标准库线程池)
1:Java库中找
2:构造方法
(1)核心线程数
(2)最大线程数
(3)保持存活时间
(4)时间单位
(5)工作任务
(6)线程工厂
①工厂模式
(7)拒绝策略(面试高频)
①中止策略
②甩锅策略
③喜新厌旧
④忠贞不渝
三:Executors(工厂类)
1:.newFixedThreadPool(可以设定固定线程数目)
2:submit添加任务
编辑3:线程池中线程数量问题
(1)前引
(2)线程任务的分类
①CPU密集型任务
②IO密集型任务
(3)分情况讨论
四:通过代码实现简单的线程池
1:思路
2:代码示例
引入:问题引入
在之前的学习中,我们了解到,为了降低频繁创建和销毁进程所带来的巨大开销,我们引入了轻量级进程的概念(线程)
现在若线程的数量进一步提升,那么线程的频繁创建和销毁所带来的资源消耗,我们也不能忽视了
所以我们进行优化,引入了“池”的概念:这里有许多种类的池,线程池,数据库连接池,进程池......(提前把需要用到的对象准备好,用完的 对象也不要直接扔掉,放到池子中以便下次使用)
一:解决方案
1:方案一——协程/纤程
注:可以理解为轻量级线程
(1)本质
通过用户态代码进行调度,不靠系统内核的调度器调度(节省了调度的开销)
注:在java21中“虚拟线程”就是这个意思。
在用户代码中,协程是基于线程进行封装的。
go是比较早支持协程的,因为语法简单就火了
2:方案二——线程池
(1)本质
提前创建好线程,需要用的时候直接从池子里拿出来用,用完了也不要释放而是返还回池子中。
(2)优缺点
①优点:节省了创建和销毁线程带来的资源消耗,更高效
②缺点:占用了内存空间
(3)解释高效的原因
从线程池里获取线程,是在用户态代码中进行调度,是可控的,高效的
从操作系统中获取线程,是在系统内核中进行完成的,不可控,低效。

二:ThreadPoolExecutor(标准库线程池)
1:Java库中找
注:打开网站Overview (Java Platform SE 8 ),找到对应的包和class类


2:构造方法

我们直接看带有7个参数的构造方法
(1)核心线程数
int corePoolSize
core(核心)pool(池)siz(大小)
(2)最大线程数
int maximumPoolSize
核心线程可以理解为公司的正式员工,不能轻易裁掉;
普通线程可以理解为公司的实习生,裁掉比较容易
最大线程数 = 核心线程数 +普通线程数
(3)保持存活时间
long keepAliveTime
(4)时间单位
TimeUnit unit
单位:s,min,hour.......
普通线程能空闲的最大时间,超过空闲时间限制,就会被移除线程池
还是用上述例子举例,实习生不能说开就开,假定摸鱼时间限制为1个小时,只要实习生摸鱼的时间小于1个小时就不会被开,超过就被开
(5)工作任务
BlockingQueue<Runnable> workQueue
与定时器(上篇文章)相似,线程池可以持有多个任务
Runnable用来描述任务的主体
<>也可以写PriorityQueue优先级队列
(6)线程工厂
ThreadFactory threadFactory
①工厂模式
通过(“工厂类”)类里面的(不一定是静态的)方法,对方法内部的new对象进行构造,完成对象的初始化(相当于,给构造方法外面在套上一层方法——套娃“封装”)


(7)拒绝策略(面试高频)
RejectedExecutionHandler handler——
execution(执行)handler(操作者)
问题:试想,线程池中有一个阻塞队列,存放的线程数目已经达到最大荣达,这个时候还往里面存放,那么线程池会怎么办?

①中止策略
.AbortPolicy ——
如果硬要在加新任务的话,线程池:我吃柠檬,lz新旧任务都不干了,抛出异常

②甩锅策略
.CallerRunsPolicy——
线程池:让交代给我这个任务的人自己完成这个线程,我才不干
③喜新厌旧
.DiscardOldestPolicy——
discard(丢弃)
线程池抛弃池中呆的最久最老的一个线程,迎接新欢(喜新厌旧)
④忠贞不渝
.DiscardPolicy——
丢弃要新添加的任务,继续我行我素执行线程池中本来就有的任务
三:Executors(工厂类)
因为ThreadPoolExecutor使用起来较为复杂,所以标准库中就封装了一下,提供了Executors这个版本(工厂类,在内部把ThreadPoolExecutor创建好了,并且设置了不同的参数)
1:.newFixedThreadPool(可以设定固定线程数目)

2:submit添加任务
package thread;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadDemon34 {public static void main(String[] args) {ExecutorService service = Executors.newFixedThreadPool(4);service.submit(new Runnable(){@Overridepublic void run() {System.out.println("执行线程池中第一个任务");}});}
}

返回值类型点进去
3:线程池中线程数量问题
(1)前引
我们知道,线程的运行效率,跟cpu的逻辑核心数直接相关,假设cpu的逻辑核心数为N,那线程的数量该是多少合适(2N?1.5N?N?..........)
(2)线程任务的分类
①CPU密集型任务
线程大部分时间都在CPU上运行,计算
②IO密集型任务
大部分时间都在等待IO(input,output)。例如:Scanner读取用户的输入
(3)分情况讨论
到底在线程池中添加多少线程数量合适呢?
如果线程多为CPU类型的,那线程数目尽量不要超过N
如果线程多为IO类型的,那线程数目就可以远远超过N
但是具体开发肯定是需要我们多次测试,通过观察系统资源消耗,来找出最合适的添加数目的。
四:通过代码实现简单的线程池
1:思路
大逻辑其实就是,把创建的任务提交上去,再把任务取出来,在run执行就可以了就是这么简单
我们用到的IDEA自带的顺序表,阻塞队列BlockingQueue都其实是一个工具罢了~~
2:代码示例
package thread;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;/*** Created with IntelliJ IDEA.* Description:* User: Hua YY* Date: 2024-09-27* Time: 16:48*/class MyThreadPoolExecutor{//2:创建一个顺序表来接收创建的线程private List<Thread> threadList = new ArrayList<>();//4创建一个容量合适的阻塞队列private BlockingQueue<Runnable> queue = new ArrayBlockingQueue(1000);//1:通过一个循环,n的值,来控制产生的线程的数量public MyThreadPoolExecutor(int n){for (int i = 0; i < n; i++) {Thread t = new Thread(()->{//6:把要做的任务从任务队列中不停地取出来,并且执行while(true){try {//带有阻塞的take取出元素Runnable runnable = queue.take();runnable.run();} catch (InterruptedException e) {throw new RuntimeException(e);}}});t.start();//3:threadList.add(t);}}//5:提交runnable到队列里面去public void submit(Runnable runnable) throws InterruptedException {queue.put(runnable);}
}
public class ThreadDemon35 {//大逻辑其实就是,把创建的任务提交上去,再把任务取出来,在run执行就可以了就是这么简单public static void main(String[] args) throws InterruptedException {MyThreadPoolExecutor executor = new MyThreadPoolExecutor(4);for (int i = 0 ; i < 1000 ; i++){//变量捕获int n = i;executor.submit(new Runnable() {@Overridepublic void run() {System.out.println("执行任务:" + n + " " + "当前线程为:" + Thread.currentThread().getName());}});}}
}

相关文章:
【JavaEE】——线程池大总结
阿华代码,不是逆风,就是我疯, 你们的点赞收藏是我前进最大的动力!!希望本文内容能够帮助到你! 目录 引入:问题引入 一:解决方案 1:方案一——协程/纤程 (1…...
编程中为什么使用0和1表示状态
前言 这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。 作者:神的孩子都在歌唱 我们看到很多项目都使用0和1表示某些状态信息,具体含义取决于上下文。以下是一些常见的用法: 布尔值&#x…...
C++入门基础知识90(实例)——实例15【求两数的最大公约数】
成长路上不孤单😊😊😊😊😊😊 【14后😊///C爱好者😊///持续分享所学😊///如有需要欢迎收藏转发///😊】 今日分享关于求两数的最大公约数的相关内容ÿ…...
自动化办公-Python-os模块的使用
os.path 模块的使用 在指定文件路径时,由于操作系统的差异,直接使用硬编码的路径可能会导致程序在不同平台上无法正常运行。为了解决这个问题,Python 提供了 os.path 模块,它包含了一系列用于路径操作的函数,可以帮助您…...
无人机之数据处理技术篇
一、数据采集 无人机通过搭载的各种传感器和设备,如GPS、加速度计、陀螺仪、磁力计、激光雷达(LiDAR)、高光谱相机(Hyperspectral)、多光谱相机(Multispectral)以及普通相机等,实时采集飞行过程中的各种数据。这些数据包括无人机的位置、速度、高度、姿态…...
828华为云征文|部署多功能集成的协作知识库 AFFiNE
828华为云征文|部署多功能集成的协作知识库 AFFiNE 一、Flexus云服务器X实例介绍二、Flexus云服务器X实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置2.4 Docker 环境搭建 三、Flexus云服务器X实例部署 AFFiNE3.1 AFFiNE 介绍3.2 AFFiNE 部署3.3 AFFiNE 使用 四、…...
c++(AVL树及其实现)
一、AVL树的概念 AVL树是最先发明的自平衡⼆叉查找树,AVL是⼀颗空树,或者具备下列性质的⼆叉搜索树:它的 左右子树都是AV树,且左右子树的高度差的绝对值不超过1。AVL树是⼀颗高度平衡搜索⼆叉树, 通过控制高度差去控…...
Cesium GIS项目关于湖泊识别与提取的实现
1. 引言 项目背景 随着遥感技术的发展,地理信息系统的应用越来越广泛。本项目旨在开发一个基于Cesium的地理信息系统,利用深度学习技术自动识别并显示湖泊的位置。 目标与意义 通过自动化处理大量遥感影像数据,提高湖泊监测的效率和准确性,为水资源管理和环境保护提供支…...
两个圆形 一个z里面一个z外面,z里面的大,颜色不同 html
两个圆形 一个z里面一个z外面,z里面的大,颜色不同 html <!DOCTYPE html> <html> <head> <style> .outer-circle {width: 150px;height: 150px;border-radius: 50%;background-color: #ff9999; /* 外圆的颜色 */position: relat…...
【Power Query】M函数-table
M函数-table 添加列(AddColumn):条件语句(If..then..else):容错语句(try..otherwise): 排序(ReorderColumns):筛选(Selec…...
uni-app 封装websocket 心跳检测,开箱即用
class websocketUtils {constructor(url, needbeat, options {}) {this.needbeat needbeat;this.url url;this.options options;this.ws null;this.heartbeatInterval options.heartbeatInterval || 10000; // 心跳间隔,默认为10秒 this.reconnectInterval …...
ASP.NET Core8.0学习笔记(十九)——EF Core DbSet
一、DbSet概述 1.DbSet提供了通过DbContext对表进行查询操作的路径。DbSet对应的属性名称将默认映射为实体T的表名。 2.使用DbSet<T>进行查询的方法: (1)直接在DbContext中创建对应的DbSet<T>属性 (2)使用DbSet DbContext.Set<T>方法操作数据表。…...
Android Camera 预览角度和拍照保存图片角度相关
–基于Android R(11) 关于Camera Camera Framework 的架构 Android Camera Framework 是一个分层架构,由以下组件组成: HAL(硬件抽象层): HAL 抽象底层相机硬件,提供与不同设备相机进行交互的标准接口.CameraService : Camera…...
新手如何使用Qt——方法使用
前言 那么这篇文章其实是我在使用Qt的过程当中呢,我发现在Qt使用过程中,在我理解信号和槽这个概念后,在编写槽函数数的时候,发现了自身存在的问题,我的难点是在于当我在编写槽函数的时候,我知道这个槽函数是…...
友元运算符重载函数
目录 1.定义友元运算符重载函数的语法形式 2.双目运算符重载 3.单目运算符重载 1.定义友元运算符重载函数的语法形式 (1)在类的内部,定义友元运算符重载函数的格式如下: friend 函数类型 operator 运算符(形参表&a…...
从0开始实现es6 promise类
主要由基础实现和静态类的实现两部分组成。 1 基础实现(不含静态类) 1.1 使用类实现完成构造函数 实现代码如下,构造函数传入一个回调函数,定义resolve和reject函数,将两个函数作为参数执行回调函数。 // 1. 使用类实…...
XML 编码
XML 编码 XML(可扩展标记语言)是一种用于存储和传输数据的标记语言。它由万维网联盟(W3C)开发,旨在提供一种标准的方式来结构化、存储和传输数据。XML的设计目标是既易于人类阅读,也易于机器解析。 XML的…...
AI周报(9.22-9.28)
AI应用-Siipet宠物沟通师 Siipet是一款由SiiPet公司推出的创新宠物行为分析相机,旨在通过尖端技术加深宠物与主人之间的情感联系。这款相机利用先进的AI算法,能够自动识别和分析家中宠物的行为,并提供定制化的护理建议。 SiiPet相机的核心功…...
基于RealSense D435相机实现手部姿态重定向
基于Intel RealSense D435相机和MediaPipe的手部姿态检测,进一步简单实现手部姿态与机器人末端的重定向,获取手部的6D坐标(包括位置和姿态)。 假设已经按照【基于 RealSenseD435i相机实现手部姿态检测】配置好所需的库和环境&…...
js中防抖 debounce 节流 throttle 原理 从0手动实现
1 防抖 高频触发事件时,执行损耗高的操作,连续触发过程中,只执行最后一次。 高频事件:input scroll resize等。损耗高:网络请求、dom操作。 实现防抖步骤:1.在回调函数中判断timer是否存在,存在…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
PostgreSQL——环境搭建
一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在࿰…...
微服务通信安全:深入解析mTLS的原理与实践
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、引言:微服务时代的通信安全挑战 随着云原生和微服务架构的普及,服务间的通信安全成为系统设计的核心议题。传统的单体架构中&…...
《信号与系统》第 6 章 信号与系统的时域和频域特性
目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...
2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案
一、延迟敏感行业面临的DDoS攻击新挑战 2025年,金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征: AI驱动的自适应攻击:攻击流量模拟真实用户行为,差异率低至0.5%,传统规则引…...
轻量级Docker管理工具Docker Switchboard
简介 什么是 Docker Switchboard ? Docker Switchboard 是一个轻量级的 Web 应用程序,用于管理 Docker 容器。它提供了一个干净、用户友好的界面来启动、停止和监控主机上运行的容器,使其成为本地开发、家庭实验室或小型服务器设置的理想选择…...
CppCon 2015 学习:REFLECTION TECHNIQUES IN C++
关于 Reflection(反射) 这个概念,总结一下: Reflection(反射)是什么? 反射是对类型的自我检查能力(Introspection) 可以查看类的成员变量、成员函数等信息。反射允许枚…...

