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

多线程 - 线程池

v2-d063475533f419d1183152a0252a44ee_1440w

线程池

相关的背景知识

线程池存在的意义: 使用进程来实现并发编程,效率太低了,任务太重了,为了提高效率,此时就引入了线程,线程也叫做“轻量级进程”,创建线程比创建进程更高效;销毁线程比销毁进程更高效;调度线程比调度进程更高效…此时,使用多线程就可以在很多时候代替进程来实现并发编程了.

俗话说,有对比就有伤害,线程和进程比,确实是有优势的,不过,随着并发程度的提高,我们对于性能要求标准的提高,就发现,线程的创建也没有那么轻量…当需要频繁创建销毁线程的时候,就发现,好像开销还是挺大的…想要进一步的再提高这里的效率,程序猿们就想出了两种办法:

  1. 弄一个“轻量级线程” => 协程/纤程(问题是这个东西目前还没有被加入到java标准库,无法使用)
    注: GO语言就内置了协程,因此使用Go开发并发编程程序是有一定优势的,这也是GO语言这么火的原因之一.
    • go属于语法层面支持协程
    • Java是第三方库层面上支持协程C++是标准库层面上支持
    • Python是语法层面支持…
  2. 使用线程池,来降低创建/销毁线程池的开销.
    线程池比如: 字符串常量池,数据库连接池
    事先把需要使用的线程创建好,放到"池”中.后面需要使用的时候,直接从池里获取.
    如果用完了,也还给池,这两个“动作”比创建/销毁更高效的.

为什么这两个“动作”比创建/销毁更高效的?

创建线程/销毁线程,涉及到用户态内核态之间的切换,它的创建是交由操作系统内核完成的,也就是在内核态完成的.
从“池”获取/还给“池”,是用户代码就能实现的(纯粹的用户态操作),不必交给内核操作.

一个操作系统 = 内核+配套的应用程序
内核 => 操作系统最核心的功能模块集合
配套的应用程序 => 硬件管理,各种驱动,进程管理,内存管理,文件系统…
内核需要给上层应用程序提供支持
例子: println("hello") => 应用程序调用系统内核,告诉内核,我要进行一个打印字符串操作,内核再通过驱动程序,操作显示器,完成上述功能

对“用户态”和“内核态”的理解:

image-20231009144310707

标准库中的线程池

在Java标准库中,给我们提供了现成的线程池,可以直接进行使用.

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** Created with IntelliJ IDEA.* Description:* User: fly(逐梦者)* Date: 2023-10-08* Time: 20:53*/
public class ThreadDemo26 {public static void main(String[] args) {// 创建了一个线程池,池子里现成数目固定是 10 个.ExecutorService pool = Executors.newFixedThreadPool(10);// 这个操作,使用Executors类的某个静态方法,直接构造出一个对象来 ~~ (相当于是把 new 操作,给隐藏到这样的方法后面了)// 像这样的方法,就称为"工厂方法"// 提供这个工厂方法的类,也就称为"工厂类"// 此处这个代码就使用了“工厂模式"这种设计模式for (int i = 0; i < 1000; i++) {int n = i; // 变量捕获pool.submit(new Runnable() {@Overridepublic void run() {System.out.println("hello" + n);}});}// 线程池提供的 submit 方法,可以给线程池提交若干个任务/** 运行程序之后发现, main 线程结束了,但是整个进程没结束* 线程池中的线程都是 前台线程 , 此时会组织进程结束.(前面定时器 Timer 也是同理)* */}
}

工厂模式

image-20231009145956193

这个操作.使用某个类的某个静态方法,直接构造出一个对象来(相当于是把 new操作,给隐藏到这样的方法后面了)
像这样的方法,就称为"工厂方法",提供这个工厂方法的类,也就称为“工厂类",此处这个代码就使用了“工厂模式"这种设计模式
“工厂模式": 一句话表示,使用普通的方法,来代替构造方法,创建对象.
“工厂模式”,是用来填构造方法的坑的 ~~ 唉,无奈之举!!!
例子: 假设现在有个类,来表示平面上的一个点,第一种构造方法使用笛卡尔坐标系提供的坐标,来构造点,第二种构造方法使用极坐标系提供的坐标,来构造点,
image-20231009164222226

正常来说,多个构造方法是通过"重载”的方式来提供的.重载的要求是,方法名相同,参数的个数或者类型不相同.所以,上述的两个构造方法是无法构成重载的,代码是会编译报错的.

重载(overload)和重写(override)的区别
重载(overload): 这两个方法在同一个类里是可以构成重载,分别在父类子类里,也是可能构成重载的.
重写(override): 在 Java中,方法重写是和父类子类相关的(如果是其他语言,重写方法不一定通过父类子类),本质上就是用一个新的方法,代替旧的…就得要求新的方法和旧的方法,名字/参数都得一模一样才行.

为了解决上述的这个问题,就可以使用“工厂模式”.
image-20231009170506362

备注:

  1. ExecutorService pool = Executors.newCachedThreadPool();创建的线程池,不会设定固定值,按需创建,用完之后也不会立即销毁,留着以后备用.Executors.newCachedThreadPool()Executors.newFixedThreadPool(10)和相关的工厂方法,其实都是基于ThreadPoolExecutor的封装.
  2. 其实很多设计模式,和“工厂模式”一样,也都没什么难度.只是名字听起来高大上,其实并不是什么高深莫测的东西.很多时候,设计模式,是在规避编程语言语法上的坑.
    不同的语言,语法规则不一样.因此在不同的语言上,能够使用的设计模式,可能会不同.有的设计模式,已经被融合在语言的语法内部了…日常见到的设计模式,主要是基于C++/Java/C#这样语言来展开的,这里所说的设计模式不一定适合其他语言,工厂模式,就对于Python来说没什么价值 ~~ Python构造方法,不像C++ / Java的这么坑,它可以直接在构造方法中通过其他手段来做出不同版本的区分…

image-20231009173545839

注: 官方文档,非常重要,学习过程中,要经常去翻这个文档!!

变量捕获

image-20231010004105221

在Java 中,对于变量捕获,做了一些额外的要求.在JDK 1.8之前,要求变量捕获,只能捕获 final修饰的变量.后来发现,这么做太麻烦了.在JDK1.8开始,放松了一点标准,要求不一定非得带 final关键字,只要代码中没有修改这个变量,也可以捕获.

image-20231010005710959

注: Java 的变量捕获要有不可修改的要求,但是 C++, JS 也有类似的变量捕获的语法,但是没有上述限制.

image-20231010012528922

ThreadPoolExecutor类的构造方法详解

image-20231010095225482

实际开发的时候,线程池的线程数,设定成多少合适呢?

网上的一些资料的答案: N(CPU的核数), N + 1,1.5N, 2N ……不过以上这些答案都不对. 线程池的线程数的设定多少合适是没有具体的数字的,因为不同的程序特定不同,此时要设置的线程数也是不同的.
考虑两个极端情况:
1.CPU 密集型,每个线程要执行的任务都是狂转CPU(进行一些列算术运算),此时线程池的线程数,最多不应该超过 CPU 核数.此时如果设置更多的线程数,也起不到作用,CPU密集型任务,要一直占用CPU,过多创建的线程,CPU根本调度不来.
2.IO 密集型,每个线程做的工作就是等待 IO(读写硬盘,读写网盘,等待用户输入……),此时,线程是不“吃”CPU的,因为这样的线程处于阻塞状态,不参与CPU调度……这个时候线程池多创建一些线程是可以的,不会再收制于CPU核数了.理论上来说,现在线程数设置无穷大都可以,当然,现实会因为系统的资源不够而失败.

不过,实际开发中并没有程序符合这两种理想模型…真实的程序,往往一部分要吃CPU,一部分要等待IO
具体这个程序几成工作量是吃CPU的,几成工作量是等待IO,是不确定的………
实际确定线程数量,是试出来的,通过测试/实验的方式(实践是检验真理的唯一标准).

小知识: 现在的CPU,是一个物理核心上可以有多个逻辑核心的.
8核16线程 => 8个物理核心,每个物理核心上有两个逻辑核心,每个逻辑核心同一时刻只能处理一个线程
一般情况下,对于我们程序猿来说,谈到CPU核心数指的就是逻辑核心.

线程池的“拒绝策略”

image-20231010111915034

实现线程池

~~ 自己写代码实现固定数量线程的线程池
一个线程池,里面至少有两个大的部分
1.阻塞队列,保存任务
2.若干个工作线程.

相关代码

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;/*** Created with IntelliJ IDEA.* Description: 实现简单线程池 ~~ 实现固定数量的线程池* User: fly(逐梦者)* Date: 2023-10-9* Time: 11:55*/
class MyThreadPool {// 此处只有任务,就直接使用 Runnable 即可private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();// n 表示线程的数量public MyThreadPool(int n) {// 开始创建线程for (int i = 0; i < n; i++) {Thread t = new Thread(() -> {while (true) {try {Runnable runnable = queue.take();runnable.run();} catch (InterruptedException e) {throw new RuntimeException(e);}}});t.start();}}// 注册任务给线程池public void submit(Runnable runnable) {try {queue.put(runnable);} catch (InterruptedException e) {throw new RuntimeException(e);}}}public class ThreadDemo27 {public static void main(String[] args) {MyThreadPool pool = new MyThreadPool(10);for (int i = 0; i < 1000; i++) {int n = i;pool.submit(new Runnable() {@Overridepublic void run() {System.out.println("hello " + n);}});}}
}

相关文章:

多线程 - 线程池

线程池 相关的背景知识 线程池存在的意义: 使用进程来实现并发编程,效率太低了,任务太重了,为了提高效率,此时就引入了线程,线程也叫做“轻量级进程”,创建线程比创建进程更高效;销毁线程比销毁进程更高效;调度线程比调度进程更高效…此时,使用多线程就可以在很多时候代替进程…...

vue3 setup中defineEmits与defineProps的使用案例

目录 一、defineEmits的使用 二、 defineProps的使用 总结 一、defineEmits的使用 使用说明 1、在子组件中调用defineEmits并定义要发射给父组件的方法 const emits defineEmits([foldChange]) 2、使用defineEmits会返回一个方法&#xff0c;使用一个变量emits(变量名随意…...

Vs - Qt - 下拉窗口示例

下列代码定义了一个窗口&#xff0c;窗口采用竖直布局&#xff1a;一个按钮及一个label。按下按钮时候&#xff0c;窗口扩张&#xff0c;显示label控件。再次按下按钮时&#xff0c;窗口收缩&#xff0c;隐藏label控件。 详细代码如下&#xff1a; #include <QApplication&g…...

深圳自贸区的形成与发展

深圳自贸区的形成与发展源于中国政府推出的自贸试验区政策。自贸试验区是指在特定区域内&#xff0c;允许实行特殊的行政管理措施和贸易政策&#xff0c;以促进贸易自由化、投资便利化和经济转型升级。 深圳自贸区成立于2015年4月以来&#xff0c;主要着眼于优化区域布局、提高…...

机器人中的数值优化(二十一)—— 伴随灵敏度分析、线性方程组求解器的分类和特点、优化软件

本系列文章主要是我在学习《数值优化》过程中的一些笔记和相关思考&#xff0c;主要的学习资料是深蓝学院的课程《机器人中的数值优化》和高立编著的《数值最优化方法》等&#xff0c;本系列文章篇数较多&#xff0c;不定期更新&#xff0c;上半部分介绍无约束优化&#xff0c;…...

BACnet /IP转MQTT网关

在工业自动化和楼宇自动化领域中&#xff0c;Modbus、MQTT和BACnet/IP是三种常用的通信协议。Modbus是一种串行通信协议&#xff0c;常用于连接工业电子设备&#xff1b;MQTT是一种基于发布/订阅模式的轻量级通信协议&#xff0c;适用于远程监测和控制系统&#xff1b;BACnet/I…...

Web API 基础 (Web Workers API)

Web Workers API 1、指南 1.1 使用Web Workers Web Workers是一种让Web内容在后台线程中运行脚本的简单方法。工作线程可以在不干扰用户界面的情况下执行任务。此外&#xff0c;它们还可以使用XMLHttpRequest(尽管responseXML和channel属性总是为空)或fetch(没有此类限制)执…...

如何看待程序员不写注释?

程序员对代码注释可以说是又爱又恨又双标……你是怎么看待程序员不写注释这一事件的呢&#xff1f; 对于程序员来说&#xff0c;注释是一种非常重要的实践&#xff0c;可以帮助他们自己和其他人更好地理解和维护代码。以下是一些关于注释的观点&#xff1a; 维护代码的重要性&a…...

2.6 方法

思维导图&#xff1a; 2.6.1 什么是方法 ### 2.6.1 什么是方法 **定义**: - 方法就是一段可以重复调用的代码&#xff0c;使得程序的可读性、可维护性都得以提高。 **示例**: - 假设有一个游戏中需要反复发射炮弹。而发射炮弹的代码有100行。为了避免在程序中多次写下这100…...

【排序算法】插入排序

文章目录 一&#xff1a;基本概念1.1 介绍1.2 原理1.3 插入排序法思想 二&#xff1a;代码实现2.1 源码2.2 执行结果2.3 测试八万条数据 三&#xff1a;算法分析3.1 时间复杂度3.2 空间复杂度3.3 稳定性 一&#xff1a;基本概念 1.1 介绍 插入式排序属于内部排序法&#xff0…...

Gnuradio+AM解调

1. https://wiki.gnuradio.org/index.php/PLL_Carrier_Tracking 2. https://wiki.gnuradio.org/index.php?titleComplex_to_Mag#Example_Flowgraph...

解决java.io.IOException: Broken pipe的报错

问题说明&#xff1a; 订单服务&#xff0c;查询预售但是出现Broken pipe&#xff1b; 测试版是正常的&#xff0c;正式版报错 解决方案 1、延长客户端超时时间 // 查询预售单列表 export function listPreOrder(query) {return request({url: /order/presale/list,method:…...

微信小程序--》从模块小程序项目案例23.10.09

配置导航栏 导航栏是小程序的门户&#xff0c;用户进来第一眼看到的便是导航栏&#xff0c;其起着对当前小程序主题的概括。而我们 新建的小程序 时&#xff0c;第一步变开始配置导航栏。如下&#xff1a; 配置tabBar 因为配置tabBar需要借助字体图标&#xff0c;我这里平常喜…...

爱尔眼科角膜塑形镜验配超百万,全力做好“角塑镜把关人”

你知道吗?过去的2022年&#xff0c;我国儿童青少年总体近视率为53.6%&#xff0c;其中6岁儿童为14.5%&#xff0c;小学生为36%&#xff0c;初中生为71.6%&#xff0c;高中生为81%①。儿童青少年眼健康问题俨然成为全社会关心的热点与痛点&#xff0c;牵动着每一个人的神经。 好…...

机器学习DAYX:线性回归与逻辑回归

线性回归 多重线性回归 逻辑回归...

【网络安全】网络安全的最后一道防线——“密码”

网络安全的最后一道防线——“密码” 前言超星学习通泄露1.7亿条信息事件武汉市地震监测中心遭境外网络攻击事件 一、密码起源1、 古代密码2、近代密码3、现代密码4、量子密码 二、商密专栏推荐三、如何利用密码保护账号安全&#xff1f;1、账号安全的三大危险&#xff1f;&…...

unity操作_光源组件 c#

准备工作 添加资源导入后先不管&#xff0c;现在主要学习自带Directional Light 我们首先创建一个平面Plane 然后重置一下位置 然后创建一个Cube 也重置一下位置然后修改y0.5刚好在这个平面上 ctrl d复制一个Cube 修改位置和旋转角度 给物体一个颜色 接下来创建一个点光源 我们…...

2023年全球市场氮化铝外延片总体规模、主要生产商、主要地区、产品和应用细分研究报告

按收入计&#xff0c;2022年全球氮化铝外延片收入大约9百万美元&#xff0c;预计2029年达到25百万美元&#xff0c;2023至2029期间&#xff0c;年复合增长率CAGR为 16.1%。同时2022年全球氮化铝外延片销量大约 &#xff0c;预计2029年将达到 。2022年中国市场规模大约为 百万美…...

C++特性:继承,封装,多态

继承 封装 类把⾃⼰的数据和⽅法只让可信的类或者对象操作&#xff0c;对不可信的进⾏隐藏&#xff0c;如&#xff1a;将公共的数据或⽅法使⽤public修饰&#xff0c;⽽不希望被访问的数据或⽅法采⽤private修饰 多态 即向不同对象发送同⼀消息&#xff0c;不同的对象在接收…...

交通物流模型 | 基于双向时空自适应Transformer的城市交通流预测

城市交通流预测是智能交通系统的基石。现有方法侧重于时空依赖建模,而忽略了交通预测问题的两个内在特性。首先,不同预测任务的复杂性在不同的空间(如郊区与市中心)和时间(如高峰时段与非高峰时段)上分布不均匀。其次,对过去交通状况的回忆有利于对未来交通状况的预测。基于…...

AURIX Tricore TC397开发实战:基于UDE的仿真调试与问题排查指南

1. 环境准备与工具安装 第一次接触AURIX Tricore TC397的开发板时&#xff0c;我完全被它强大的多核架构吸引住了。这款芯片在汽车电子领域应用广泛&#xff0c;但调试过程确实让不少新手头疼。经过几个项目的实战&#xff0c;我总结出一套基于UDE的调试方法&#xff0c;能帮你…...

WeatherBench终极指南:快速构建天气预报AI模型的完整基准平台

WeatherBench终极指南&#xff1a;快速构建天气预报AI模型的完整基准平台 【免费下载链接】WeatherBench A benchmark dataset for data-driven weather forecasting 项目地址: https://gitcode.com/gh_mirrors/we/WeatherBench WeatherBench是一个专为数据驱动天气预报…...

087、机器人运动学:雅可比矩阵

087、机器人运动学:雅可比矩阵 一、一个让我熬夜三天的调试故事 去年做六轴协作机器人末端力控的时候,遇到一个诡异的问题:机器人末端在某个位姿下,明明关节速度指令给得很平滑,末端速度却突然跳变,导致力控震荡。当时我盯着示波器上的速度曲线,百思不得其解——运动学…...

SOCD Cleaner终极指南:如何用开源工具解决游戏输入冲突问题

SOCD Cleaner终极指南&#xff1a;如何用开源工具解决游戏输入冲突问题 【免费下载链接】socd Key remapper for epic gamers 项目地址: https://gitcode.com/gh_mirrors/so/socd 你是否曾在激烈的游戏对战中&#xff0c;因为同时按下相反方向键而输掉关键对决&#xff…...

3分钟告别Armoury Crate:华硕笔记本轻量化控制终极指南

3分钟告别Armoury Crate&#xff1a;华硕笔记本轻量化控制终极指南 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook, Zenbook, E…...

零代码物联网实战:用WipperSnapper与Adafruit IO快速采集模拟与I2C传感器数据

1. 项目概述与核心价值在嵌入式开发和物联网项目的起步阶段&#xff0c;很多开发者&#xff0c;尤其是刚接触硬件的朋友&#xff0c;常常会卡在两个看似基础却至关重要的环节上&#xff1a;如何让微控制器“感知”到物理世界的连续变化&#xff0c;以及如何高效、可靠地读取那些…...

从电赛A题到实战:手把手教你搞定单相交流电子负载的SPWM控制与功率因数调节

从电赛A题到实战&#xff1a;手把手教你搞定单相交流电子负载的SPWM控制与功率因数调节 在电子设计竞赛中&#xff0c;单相交流电子负载的设计一直是极具挑战性的题目。它不仅考验参赛者对电力电子技术的理解&#xff0c;更要求具备将理论转化为实际电路的能力。本文将从硬件选…...

repomix:智能代码库混合工具,为AI编程与项目分析提供结构化输入

1. 项目概述&#xff1a;当代码库成为“黑盒”&#xff0c;我们需要一把钥匙 在软件开发的日常中&#xff0c;我们常常会面对一个既熟悉又头疼的场景&#xff1a;接手一个全新的、或者许久未碰的代码仓库。面对动辄几十上百个文件、错综复杂的目录结构&#xff0c;以及那些命名…...

终极DirectDraw兼容性解决方案:让经典游戏在Windows 11上重获新生

终极DirectDraw兼容性解决方案&#xff1a;让经典游戏在Windows 11上重获新生 【免费下载链接】DDrawCompat DirectDraw and Direct3D 1-7 compatibility, performance and visual enhancements for Windows Vista, 7, 8, 10 and 11 项目地址: https://gitcode.com/gh_mirror…...

深入JPEG文件结构:用Python和十六进制编辑器‘解剖’一张图片,理解tiny_jpeg.h的写入逻辑

逆向工程JPEG&#xff1a;用Python和十六进制工具解析tiny_jpeg.h的编码逻辑 当你用手机拍下一张照片&#xff0c;或是从网上下载一张图片时&#xff0c;这些图像大多以JPEG格式存储。但你是否好奇过&#xff0c;这个看似简单的.jpg文件内部究竟隐藏着怎样的结构&#xff1f;本…...