【JavaEE初阶】深入理解线程池的概念以及Java标准库提供的方法参数分析

news2024/11/25 6:43:21

前言

🌟🌟本期讲解关于MySQL索引事务,希望能帮到屏幕前的你。

🌈上期博客在这里:【JavaEE初阶】多线程案列之定时器的使用和内部原码模拟-CSDN博客

🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客

目录

📚️1.引言 

 📚️2.线程池的基本认知

2.1线程池的概念

2.2 线程池的引入

1.引入协程

2.引入线程池

 2.3标准库中的线程池

1.corePoolSize与maximumPoolSize

2.keepAliveTime和TimeUnit

 3.BlockingQueue

4.ThreadFactory

5. RejectedExecutionHandler

 📚️3.线程池的基本使用

3.1Executor的使用

3.2线程池中线程数量

 3.3线程池的实现

1.构造阻塞队列

2.构造方法

3.submit方法

4.主函数

5.输出

 📚️4.总结

📚️1.引言 

      Hello!!!家人们,国庆是否过得快乐呢??本期小编将讲解关于多线程中比较重要的一个概念,即线程池的概念,以及工厂模式在线程池中的使用,准备好了吗~~~🥳🥳🥳;

且听小编进行讲解,包你学会!!! 

 📚️2.线程池的基本认知

2.1线程池的概念

        线程池是一组预先创建好的线程集合,这些线程处于等待分配任务的状态。当有任务需要执行时,无需创建新线程,而是从线程池中获取一个空闲线程来执行任务。任务完成后,线程不会被销毁,而是返回线程池继续等待下一个任务。

通俗总结:

1.线程池就是一个存储线程的地方,用使用时就从这里取空闲的线程

2.使用过后,线程放回线程池,不被销毁,等待下一个任务

2.2 线程池的引入

最开始,引入了进程,解决了并发编程的问题,但是由于频繁的创建销毁进程,造成了成本消耗提高,此时就引入了线程

此时又因为线程的频繁创建和开销,所造成的成本消耗是不可以忽视的(抛开剂量谈毒性,都是耍流氓),那么就有以下两种办法

1.引入协程

这里的协程也叫做纤程,即轻量化线程;

本质:协程的本质就是通过用户态代码进行控制的,不是通过内核中的调度器进行调度的;

在用户态代码中协程是通过线程进行封装的可能是N个协程对应一个线程,还有可能是N个协程对应M个线程,一个代码中可以创建很多的协程,但是不能创建很多的线程~~~ 

2.引入线程池

 由于其线程池的概念,可以知道,线程池降低了线程频繁创建销毁的成本消耗,所以就引入了线程池;

为啥线程池取线程比系统中申请线程更高效呢???

假如我们在银行中要进行打印某个证件,我们可以自己去打印或者喊工作人员进行帮助,如下图;

那么此时如果银行人员进行帮助,就会消失在我们的视野,我们不知道 他去干嘛了,此时就是不可控制的,那么对应的效率就比较低;但是当我们自己去打印,就是我们可以控制的,效率高

注意:

从线程池里取线程,是纯用户态的代码(可以控制,效率更高)

通过系统申请线程,是内核态(不可控制,效率更低)

 2.3标准库中的线程池

在Java标准库中提供了,关于线程池的构造方法即ThreadPoolExecutor,那么这个方法在Java文档中有很多的参数,小编将一一解释;

1.corePoolSize与maximumPoolSize

 corePoolSize:即核心线程数,一个线程池里,最少得有多少个任务;

maximumPoolSize:即最大线程数,一个线程池里,最多有多少个线程;

在标准库提供的线程数目不是一成不变的,这是根据当前的任务的多少来决定的,任务少线程少,任务多线程多,这是一个自适应的过程;

2.keepAliveTime和TimeUnit

这两个是联合进行是使用的,即线程在线程池中空闲状态下能存活多久前面表示数字,后面表示的是时间单位(h,ms,s...) 

即线程超过空闲时间后,机会进行销毁,再次使用时再创建一个新的线程;

 3.BlockingQueue<Runnable>

这里用runnable作为描述任务的主体,和定时器哪里的是类似的;

4.ThreadFactory

即工厂模式,是一种常见的设计模式,通过专门的工厂类来进行对象的创建,这里就是通过工厂类创建线程对象 

这个类提供了方法封装了newThread,给Thread设置了一些属性

5. RejectedExecutionHandler

即拒绝策略,当任务太多,此时线程池有阻塞队列,容纳的任务已经上限了,此时就要进行一些操作,再Java文档中有以下几个策略;

1.第一种

解释:即抛出异常,旧的任务和新的任务都不执行了;

2.第二种

解释:新的任务由引进任务的线程进行执行,线程池不执行这个任务,继续做自己的任务

 3.第三种

解释:即线程池舍去一个最老的任务,添加新的任务进行执行

4.第四种

 

解释:不管这个任务,线程池继续做自己的任务

 📚️3.线程池的基本使用

有上述的线程池的介绍中,我们知道ThreadPoolExecutor是非常复杂,参数是比较多多,所以在Java标准库中还有介绍了一种简单的版本

即Executor工厂类,通过这个类创建线程对象,内部已经对 ThreadPoolExecutor 进行了参数的设置,

3.1Executor的使用

创建对象,代码如下:

ExecutorService service= Executors.newFixedThreadPool(4);

 在此时Executors点出来的方法不止一个,如下图:

 具体代码的使用:

1.实现Fix表示方法的使用,即规定线程池的线程数量

代码如下:

 ExecutorService service= Executors.newFixedThreadPool(3);
        service.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("工厂类创建的线程池对象");
            }
        });

这里就是表示的是规定的线程数量为3个,submit进行任务的添加;

2.规定时间进行任务的执行

代码如下:

 ScheduledExecutorService service1=Executors.newScheduledThreadPool(1);
        service1.schedule(()->{
            System.out.println("111");
        },3,TimeUnit.SECONDS);
        service1.shutdown();

这里的1表示的是核心线程数目,这里通过schedule来添加定时执行的任务,3表示数字SECONDS表示的是秒,即三秒后再执行;

3.2线程池中线程数量

这里设计线程池规定的线程数量的时候,是要根据具体的代码来进行分析的;

CPU密集型任务:即线程大部分的时间都在CPU上进行计算;

IO密集型任务:即任务大部分时间都在等待IO不用去CPU上进行计算;

那么此时:如果是所有任务都是CPU密集型任务,那么此时线程数目就不能超过CPU逻辑核心数;反之如全都是IO密集型任务,此时线程数目就可以远远大于逻辑核心数目;(极端的情况下)

解决:尝试给线程池设定不同的线程数目,观察线程时间开销和系统资源占用开销的占比,来找到合适的值; (线程数目增加,时间开销下降,系统资源占用增加,反之则反)

 3.3线程池的实现

这里就是四部走的过程:

1.提供构造方法,指定线程数目

2.在构造方法中创建并启动线程

3.阻塞队列的持有的要执行任务

4.submit方法提供执行任务

1.构造阻塞队列

 代码如下:

BlockingQueue<Runnable> queue=new ArrayBlockingQueue(100);

这里的runnable就是任务执行的主体

2.构造方法

代码如下:

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

解释:这里的n代表包含的线程数目,在外部循环是在线程创建的时候执行,while循环是为了保证线程不断对阻塞队列进行扫描,执行任务,如果为空那么此时就发生阻塞;

3.submit方法

代码如下:

public void submit(Runnable runnable) throws InterruptedException {
        queue.put(runnable);
    }

解释:通过这个方法进行任务的输入,与主函数对应

4.主函数

代码如下:

 public static void main(String[] args) throws InterruptedException {
        MyThreadPoolExecutor myThreadPoolExecutor=new MyThreadPoolExecutor(4);
        for (int i = 1; i <100 ; i++) {
            int n=i;
            myThreadPoolExecutor.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("这是线程"+Thread.currentThread().getName()+"执行第"+n+"个任务");
                }
            });
        }
    }

解释:实例化对象后,通过for循环持续进行任务的输入,这里的n是为了防止变量捕获,实现日志的打印;这种方法的执行,小编在上期的定时器的写法类似哦;

5.输出

图片演示如下:

可以看到这里的执行过程不是严格的升序执行的,所以这里即存在任务的抢占;(这里小编只是截取了一部分输出案列) 

 📚️4.总结

💬💬本期小编主要讲解了关于线程池的基本概念认知,为啥引入线程池,并且线程池中拒绝策略是什么,以及我们如何实现线程池的模拟,也提供了代码供各位uu进行参考~~~;

在线程池的模拟中小编的代码上传Gitee了:GGBondlctrl/Thread (gitee.com)

🌅🌅🌅~~~~最后希望与诸君共勉,共同进步!!!


💪💪💪以上就是本期内容了, 感兴趣的话,就关注小编吧。

                             😊😊  期待你的关注~~~

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

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

相关文章

ScholarAI发一个月会员啦!

诸神缄默不语-个人CSDN博文目录 ScholarAI是一个用于学术的工具&#xff0c;用LLM智能检索用户所需的论文&#xff0c;可以进行简单的总结和分析。可以理解成“LLM帮你读论文”这种感觉。 这次之所以发会员是因为GPT Store服务出问题了&#xff0c;所以给了用户一个月会员作为…

双向数据库迁移工具:轻松实现 MySQL 与 SQLite 数据互导

项目概述与作用 该项目的核心是实现 MySQL 和 SQLite 两种数据库之间的数据迁移工具。它能够轻松地将 MySQL 数据库中的数据导出为 SQLite 数据库文件&#xff0c;反过来也可以将 SQLite 数据库中的数据上传到 MySQL 数据库中。这个双向迁移工具非常适用于&#xff1a; 数据库备…

【C++】--类和对象(2)

&#x1f44c;个人主页: 起名字真南 &#x1f446;个人专栏:【数据结构初阶】 【C语言】 【C】 目录 1 类的默认成员函数2 构造函数3 析构函数4 拷贝构造5 赋值运算符重载5.1 运算符重载5.2 赋值运算符的重载 1 类的默认成员函数 默认成员函数就是用户没有显示实现&#xff0c;…

制作U盘启动盘1 — UltraISO

官网&#xff1a;UltraISO软碟通中文官方网站 - 光盘映像文件制作/编辑/转换工具 点击工具栏的“打开”&#xff0c;在弹出的窗口选择要刻录的ISO文件。 点击菜单栏的“启动”—“写入磁盘映像”。 硬盘驱动器选择要刻录的U盘。 点击写入&#xff0c;会弹出数据丢失的提示&…

数据结构和算法简介

目录 1.认识数据结构 什么是数据结构 逻辑结构 物理结构 常见的数据结构 2.认识算法 什么是算法 如何衡量算法效率 时间复杂度 什么是时间复杂度 如何计算时间复杂度 大O渐进表示法 常见时间复杂度计算例子 空间复杂度 什么是空间复杂度 如何计算空间复杂度 常…

【数据结构】深度解析堆排序

目录 &#x1f4af;引言 &#x1f4af;堆的概念 &#xff08;一&#xff09;什么是堆 &#xff08;二&#xff09;堆的表示 &#x1f4af;堆排序原理 &#xff08;一&#xff09;建堆 &#xff08;二&#xff09;排序 &#x1f4af;代码实现 &#x1f4af;代码分析 &…

【Sqlite】sqlite内部函数sqlite3_value_text特性

目录 ⚛️1 结论 ☪️2 说明 ☪️3 传入数值转成科学计数法 ♋3.1 只有整数部分 ♏3.2 只有小数部分 ♐3.3 整数小数 ⚛️1 结论 整数(sqlite视为int64)位数 > 20位&#xff0c;sqlite3_value_text 采用科学计数法。否则正常表示。 浮点数(sqlite视为double)的整数部…

STM32 通用同步/异步通信

一、串行通信简介 CPU与外围设备之间的信息交换称为通信。基本的通信方式有并行通信和串行通信两种。STM32单片机提供了功能强大的串行通信模块&#xff0c;即通用同步/异步收发器&#xff08;USART&#xff09;。 1.串行通信 串行通信是数据字节一位一位地依次传送的通信方式。…

HarmonyOS第一课 05 从简单的页面开始-习题

【习题】从简单的页面开始 通过/及格分80/ 满分100 判断题 1.Button作为容器使用时可以通过添加子组件实现包含文字、图片等元素的按钮&#xff0c;其类型包括胶囊按钮、圆形按钮、普通按钮。T 正确(True) 错误(False) 大部分前端框架的按钮都具有这几个类型,鸿蒙也不例外…

Ubuntu+VsCode++搭建C++开发环境

Ubuntu下使用VsCode搭建C开发环境 1、基本工具的安装 首先Ubuntu下安装好C开发的一个些基本工具g、gdb、make、cmake等&#xff0c;安装方式点这里 检查一下安装环境 $ g --version g (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0 Copyright (C) 2021 Free Software Foundation,…

位图的应用

目录 问题引入 位图概念 位图的实现 应用2&#xff1a;找到只出现一次的整数 应用三&#xff1a;找交集 STL中的位图 问题引入 面试题 给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&#xff0c;如何快速判断一个数是否在 这40亿个数中。【腾讯】 解决…

幂,你去哪儿了-《分析模式》漫谈37

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 “Analysis Patterns”的第3章的图3.5&#xff0c;原文的图是&#xff1a; 2004&#xff08;机械工业出版社&#xff09;中译本的图是&#xff1a; direct翻译成分子&#xff0c;inv…

master节点k8s部署]33.ceph分布式存储(四)

总结ceph分布式存储&#xff08;三&#xff09;中提到的三种方法&#xff1a; 1.创建rbda&#xff0c;并且在创建pv的时候配置该rbda,以下代码仅展示关键信息。 [rootxianchaomaster1 ~]# cat pv.yaml apiVersion: v1 kind: PersistentVolume metadata: name: ceph-pv ...…

MySQL多表查询:行子查询

先看我的表数据 dept表 emp表 行子查询 子查询返回的结果是一行&#xff08;可以是多列&#xff09;, 这种子查询称为行子查询 常用的操作符: , <>, IN, NOT IN 例子1. 查询与“张无忌” 的薪资及直属领导相同的员工信息 拆解成两个问题 a. 查询"张无忌"…

基于SpringBoot+Vue+MySQL的汽车租赁系统

系统展示 用户前台界面 管理员后台界面 系统背景 随着城市化和交通需求的不断增加&#xff0c;汽车租赁业务成为了现代社会的一个重要组成部分。汽车租赁服务为人们提供了一种灵活便捷的交通解决方案&#xff0c;让用户在无需购买车辆的情况下&#xff0c;根据实际需要租赁车辆…

端口冲突的解决方案以及SpringBoot自动检测可用端口demo

端口冲突的解决方案 端口冲突通常发生在尝试运行两个或多个应用程序或服务时&#xff0c;它们尝试使用同一个端口号&#xff0c;导致系统无法正确分配资源。 各种端口错误 你是否遇到过下面这些报错信息呢&#xff1f; Windows 系统报错&#xff1a; 系统错误 1004 套接字操作…

图像转3D视差视频:DepthFlow、kling

1、DepthFlow 参看: https://github.com/BrokenSource/DepthFlow 通过深度图实现图像3d效果 安装 https://brokensrc.dev/get/pypi/#installing pip insatll depthflow shaderflow broken-source pianola spectronote turbopipe 使用 1、下载项目 git clone https://gith…

约数个数约数之和

好久没发文章了.......不过粉丝还是一个没少...... 今天来看两道超级恶心的数论题目&#xff01; No.1 约数个数 No.2 约数之和 先来看第一道&#xff1a;约数个数 题目描述 给定 n 个正整数 ai​,请你输出这些数的乘积的约数个数,答案对 10^97 取模 输入格式 第一行包含…

Python_文件处理

一个完整的程序一般都包括数据的存储和读取&#xff1b;我们在前面写的程序数据都没有进行实际的存储&#xff0c;因此python解释器执行完数据就消失了。实际开发中&#xff0c;我们经常需要从外部存储介质&#xff08;硬盘、光盘、U盘等&#xff09;读取数据&#xff0c;或者将…

微信小程序开发-目录结构介绍

文章目录 一&#xff0c;目录结构介绍1&#xff0c;主体文件2&#xff0c;页面文件3&#xff0c;修改页面渲染模式 二&#xff0c;新增页面1&#xff0c;右键“pages”-新建文件夹2&#xff0c;右键文件夹-新建page3&#xff0c;新建页面的快捷方式 四&#xff0c;基础库设置 一…