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

【JavaEE】——线程池大总结

8e19eee2be5648b78d93fbff2488137b.png

阿华代码,不是逆风,就是我疯,

你们的点赞收藏是我前进最大的动力!!希望本文内容能够帮助到你!

目录

 

引入:问题引入

一:解决方案

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)解释高效的原因

从线程池里获取线程,是在用户态代码中进行调度,是可控的,高效的

从操作系统中获取线程,是在系统内核中进行完成的,不可控,低效。

d9d7e3ce0b0a4962bbfed46e54794091.png

二:ThreadPoolExecutor(标准库线程池)

1:Java库中找

注:打开网站Overview (Java Platform SE 8 ),找到对应的包和class类

0bd458fa4e224b228cdd4015390c97cc.png6e6683c97721479fafbf61c0300326da.png

2:构造方法

6e2ebb9fc3604278acb46a94525d104b.png

我们直接看带有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对象进行构造,完成对象的初始化(相当于,给构造方法外面在套上一层方法——套娃“封装”)

1026669ae539467eba5db3feddc92d69.png

56d76f658d634176af0e1525b9c47803.png

 

(7)拒绝策略(面试高频)

RejectedExecutionHandler handler——

execution(执行)handler(操作者)

问题:试想,线程池中有一个阻塞队列,存放的线程数目已经达到最大荣达,这个时候还往里面存放,那么线程池会怎么办?

d00ce6ae559744cebd67b9a6568ccf83.png

①中止策略

.AbortPolicy ——

如果硬要在加新任务的话,线程池:我吃柠檬,lz新旧任务都不干了,抛出异常

651361d0a53a442aae9e3ae6feaec96d.png

②甩锅策略

.CallerRunsPolicy——

线程池:让交代给我这个任务的人自己完成这个线程,我才不干

③喜新厌旧

.DiscardOldestPolicy——

discard(丢弃)

线程池抛弃池中呆的最久最老的一个线程,迎接新欢(喜新厌旧)

④忠贞不渝

.DiscardPolicy——

丢弃要新添加的任务,继续我行我素执行线程池中本来就有的任务

三:Executors(工厂类)

因为ThreadPoolExecutor使用起来较为复杂,所以标准库中就封装了一下,提供了Executors这个版本(工厂类,在内部把ThreadPoolExecutor创建好了,并且设置了不同的参数)

1:.newFixedThreadPool(可以设定固定线程数目)

c4ea4d8220f54f039b6a7b0ccf4082f6.png

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("执行线程池中第一个任务");}});}
}

edd48773c8d94b3980f8bae858716683.png

返回值类型点进去

ac27eadab28f421b841c96ae04be4c54.png3:线程池中线程数量问题

(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());}});}}
}

2a747122a79e46c58058b5cb54441881.png

 

相关文章:

【JavaEE】——线程池大总结

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯&#xff0c; 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01;希望本文内容能够帮助到你&#xff01; 目录 引入&#xff1a;问题引入 一&#xff1a;解决方案 1&#xff1a;方案一——协程/纤程 &#xff08;1…...

编程中为什么使用0和1表示状态

前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子都在歌唱 我们看到很多项目都使用0和1表示某些状态信息&#xff0c;具体含义取决于上下文。以下是一些常见的用法&#xff1a; 布尔值&#x…...

C++入门基础知识90(实例)——实例15【求两数的最大公约数】

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///C爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于求两数的最大公约数的相关内容&#xff…...

自动化办公-Python-os模块的使用

os.path 模块的使用 在指定文件路径时&#xff0c;由于操作系统的差异&#xff0c;直接使用硬编码的路径可能会导致程序在不同平台上无法正常运行。为了解决这个问题&#xff0c;Python 提供了 os.path 模块&#xff0c;它包含了一系列用于路径操作的函数&#xff0c;可以帮助您…...

无人机之数据处理技术篇

一、数据采集 无人机通过搭载的各种传感器和设备&#xff0c;如GPS、加速度计、陀螺仪、磁力计、激光雷达(LiDAR)、高光谱相机(Hyperspectral)、多光谱相机(Multispectral)以及普通相机等&#xff0c;实时采集飞行过程中的各种数据。这些数据包括无人机的位置、速度、高度、姿态…...

828华为云征文|部署多功能集成的协作知识库 AFFiNE

828华为云征文&#xff5c;部署多功能集成的协作知识库 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树是最先发明的自平衡⼆叉查找树&#xff0c;AVL是⼀颗空树&#xff0c;或者具备下列性质的⼆叉搜索树&#xff1a;它的 左右子树都是AV树&#xff0c;且左右子树的高度差的绝对值不超过1。AVL树是⼀颗高度平衡搜索⼆叉树&#xff0c; 通过控制高度差去控…...

Cesium GIS项目关于湖泊识别与提取的实现

1. 引言 项目背景 随着遥感技术的发展,地理信息系统的应用越来越广泛。本项目旨在开发一个基于Cesium的地理信息系统,利用深度学习技术自动识别并显示湖泊的位置。 目标与意义 通过自动化处理大量遥感影像数据,提高湖泊监测的效率和准确性,为水资源管理和环境保护提供支…...

两个圆形 一个z里面一个z外面,z里面的大,颜色不同 html

两个圆形 一个z里面一个z外面&#xff0c;z里面的大&#xff0c;颜色不同 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 添加列&#xff08;AddColumn&#xff09;&#xff1a;条件语句&#xff08;If..then..else&#xff09;&#xff1a;容错语句&#xff08;try..otherwise&#xff09;&#xff1a; 排序&#xff08;ReorderColumns&#xff09;&#xff1a;筛选&#xff08;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; // 心跳间隔&#xff0c;默认为10秒 this.reconnectInterval …...

ASP.NET Core8.0学习笔记(十九)——EF Core DbSet

一、DbSet概述 1.DbSet提供了通过DbContext对表进行查询操作的路径。DbSet对应的属性名称将默认映射为实体T的表名。 2.使用DbSet<T>进行查询的方法&#xff1a; (1)直接在DbContext中创建对应的DbSet<T>属性 (2)使用DbSet DbContext.Set<T>方法操作数据表。…...

Android Camera 预览角度和拍照保存图片角度相关

–基于Android R(11) 关于Camera Camera Framework 的架构 Android Camera Framework 是一个分层架构&#xff0c;由以下组件组成&#xff1a; HAL&#xff08;硬件抽象层&#xff09;: HAL 抽象底层相机硬件,提供与不同设备相机进行交互的标准接口.CameraService : Camera…...

新手如何使用Qt——方法使用

前言 那么这篇文章其实是我在使用Qt的过程当中呢&#xff0c;我发现在Qt使用过程中&#xff0c;在我理解信号和槽这个概念后&#xff0c;在编写槽函数数的时候&#xff0c;发现了自身存在的问题&#xff0c;我的难点是在于当我在编写槽函数的时候&#xff0c;我知道这个槽函数是…...

友元运算符重载函数

目录 1.定义友元运算符重载函数的语法形式 2.双目运算符重载 3.单目运算符重载 1.定义友元运算符重载函数的语法形式 &#xff08;1&#xff09;在类的内部&#xff0c;定义友元运算符重载函数的格式如下&#xff1a; friend 函数类型 operator 运算符&#xff08;形参表&a…...

从0开始实现es6 promise类

主要由基础实现和静态类的实现两部分组成。 1 基础实现&#xff08;不含静态类&#xff09; 1.1 使用类实现完成构造函数 实现代码如下&#xff0c;构造函数传入一个回调函数&#xff0c;定义resolve和reject函数&#xff0c;将两个函数作为参数执行回调函数。 // 1. 使用类实…...

XML 编码

XML 编码 XML&#xff08;可扩展标记语言&#xff09;是一种用于存储和传输数据的标记语言。它由万维网联盟&#xff08;W3C&#xff09;开发&#xff0c;旨在提供一种标准的方式来结构化、存储和传输数据。XML的设计目标是既易于人类阅读&#xff0c;也易于机器解析。 XML的…...

AI周报(9.22-9.28)

AI应用-Siipet宠物沟通师 Siipet是一款由SiiPet公司推出的创新宠物行为分析相机&#xff0c;旨在通过尖端技术加深宠物与主人之间的情感联系。这款相机利用先进的AI算法&#xff0c;能够自动识别和分析家中宠物的行为&#xff0c;并提供定制化的护理建议。 SiiPet相机的核心功…...

基于RealSense D435相机实现手部姿态重定向

基于Intel RealSense D435相机和MediaPipe的手部姿态检测&#xff0c;进一步简单实现手部姿态与机器人末端的重定向&#xff0c;获取手部的6D坐标&#xff08;包括位置和姿态&#xff09;。 假设已经按照【基于 RealSenseD435i相机实现手部姿态检测】配置好所需的库和环境&…...

js中防抖 debounce 节流 throttle 原理 从0手动实现

1 防抖 高频触发事件时&#xff0c;执行损耗高的操作&#xff0c;连续触发过程中&#xff0c;只执行最后一次。 高频事件&#xff1a;input scroll resize等。损耗高&#xff1a;网络请求、dom操作。 实现防抖步骤&#xff1a;1.在回调函数中判断timer是否存在&#xff0c;存在…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值&#xff0c;最大值左侧的数值严格单调递增&#xff0c;最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值&#xff0c;最小值左侧的数值严格单调递减&#xff0c;最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

Vite中定义@软链接

在webpack中可以直接通过符号表示src路径&#xff0c;但是vite中默认不可以。 如何实现&#xff1a; vite中提供了resolve.alias&#xff1a;通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具&#xff1a;make/makfile 1.背景 在一个工程中源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;mak…...