(JAVA)-(多线程)-线程池

线程池,顾名思义就是存放线程的池子,当有任务时能够随时取用线程,任务结束后能够放回线程池中。如果把线程比成碗,线程池就像一个碗柜一样。

使用线程池的好处:

1.当有大量线程对象时,减少了线程创建销毁造成的损耗。

2.提高响应速度

3.提高线程的可管理性

线程池的核心逻辑:

1.创建一个池子,池子是空的

2.提交任务的时候池子会创建新的线程对象,任务执行完毕,线程归还给池字,下次再提交任务时,不需要创建新的线程,直接复用已有的线程即可

3.提交任务时,池子中没有空闲的线程,也无法创建新的线程,任务就会排队

代码实现:

1.创建线程池

2.提交任务

3.所有的任务全部执行完毕,关闭线程

一:使用Executors工具类创建线程池对象

Executors是线程池的一个工具类,能调用他的静态方法创建线程池对象

public static ExecutorService newCachedThreadPool();
//创建一个没有上限的线程池
public static ExecutorService newFixedThreadPool(int nThreads);
//创建一个有上限的线程池

1.newCachedThreadPool() 方法:

能创建一个没有上限的线程池,如果现有任务没有线程进行处理,就会创建一个新线程并添加到缓存池中。如果有被使用完但是还没销毁的线程,就复用该线程。如果有线程60s未被使用的话就会从缓存中移出并终止(销毁)。因此,长时间保持空闲的线程池不会使用任何资源。

 ExecutorService pool1 = Executors.newcachedThreadPool();

提交任务:submit方法

可以看到submit方法参数可以传递runnable和Callable的实现类任务

public class test {
    public static void main(String[] args) {
        ExecutorService pool1 = Executors.newCachedThreadPool();
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
//提交三个任务
        pool1.shutdown();
    }
}

 class MyRunnable implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName()+"---"+i);
        }
    }
}

我们可以看到线程池创建了三个线程。

2.newFixedThreadPool(int num)方法

这个方法能创建一个固定线程数的线程池,超出线程任务数量的线程会在队列中等待,方法参数为线程池中的线程数

public class test {
    public static void main(String[] args) {
        ExecutorService pool1 = newFixedThreadPool(1);
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
        pool1.submit(new MyRunnable());
//提交三个任务
        pool1.shutdown();
    }
}

 class MyRunnable implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName()+"---"+i);
        }
    }
}

我们可以看到结果中只有线程1在执行任务。

二:自定义线程池

我们首先对Executors工具类进行跟进

我们发现创建这个线程池的方法在底层调用了一个 ThreadPoolExecutor类去创建了对象,并且传递了一些参数进去,ThreadPoolExecutor其实就是线程池的类。

我们先讲解线程池的运行流程

线程池中分为核心线程和临时线程。临时线程倘若经过了一定时间没有处理,就会进行销毁

当任务进行提交时,线程池便会创建线程。

倘若提交的任务数超过了核心线程数,就会在阻塞队列中进行等待,直到核心线程正在进行的任务完成后再执行。倘若提交的任务数超出了阻塞队列的长度,就会进入临时队列中进行执行,若提交的任务在超出了临时队列的范围,就会是使用任务拒绝策略拒绝任务。

通过以上,我们了解了线程池的运行流程。接着我们来看看线程池的参数

跟进发现,线程池这个类最长的构造方法有七个参数,我们逐个讲解

1.corePoolSize:这个参数就是线程池的核心线程数。

2.maximumPoolSize:这个参数是线程池的最大线程数,他肯定是大于核心线程数,从源码中也可以看到,如果这样做在运行时会抛出异常:IllegalArgumentException。

3.keepAliveTime:这个参数是空闲线程的等待时间,当超过这个时间临时线程还没有执行任务,临时线程就会销毁。

4.unit:这个是线程池的空闲时间的单位,需要调用TimeUnit中的枚举常量

  • 它在TimeUnit类中有7种静态属性可取。
    • 天:TimeUnit.DAYS;
    • 小时:TimeUnit.HOURS;
    • 分钟:TimeUnit.MINUTES;
    • 秒:TimeUnit.SECONDS;
    • 毫秒:TimeUnit.MILLISECONDS;
    • 微妙:TimeUnit.MICROSECONDS;
    • 纳秒:TimeUnit.NANOSECONDS;

5.workQueue:这个参数是线程在等待的阻塞队列,需要传递一个阻塞队列进去。

6.theadFactor:这个参数意思是线程工厂,用于创建新的线程。我们可以传递Executros工具类中的deafaultThread方法进行创建线程工厂,他在底层也是创建了一个线程。

7.rejectedExecutionHandler:这个是一个接口,代表任务的拒绝策略,在ThreadPoolExecutor中以内部类的方式内部类方式存在,他们都实现了rejectedExecutionHandler接口。

  • AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。线程池默认的拒绝策略。如何使用new ThreadPoolExecutor.AbortPolicy()
  • DiscardPolicy:也是丢弃任务,但是不抛出异常。
  • DiscardOldestPolicy:丢弃队列最前面的任务,也就是队列头的元素,然后重新尝试执行任务(重复此过程)。如果此时阻塞队列使用PriorityBlockingQueue优先级队列,将会导致优先级最高的任务被抛弃。
  • CallerRunsPolicy:既不抛弃任务也不抛出异常,而是由调用线程的主线程来处理该任务。换言之就是由调用线程池的主线程自己来执行任务(例如:是有main线程启动的线程池,当触发次策略时,多余的任务就会交由main线程来执行),因此在执行任务的这段时间里主线程无法再提交新任务,从而使线程池中工作线程有时间将正在处理的任务处理完成,所以对性能和效率必然是极大的损耗。

那么线程池多大合适呢?

要理解上面的公式,我们得先了解最大并行数是什么

四核八线程:代表着电脑有四个大脑 ,能同时干四件事情,而超线程技术,把一个物理核心模拟成两个逻辑核心,理论上要像八颗物理核心一样在同一时间执行八个线程,所以电脑最大并行数为8.

我们可以用RunTime工具类中的availiableProcessors()静态方法去获取java能够使用的最大线程数。

项目运算比较多,读取本地文件或者数据库比较少,就属于cpu密集型运算,反之则属于IO密集型运算

第一个公式很容易能看懂,那么第二个公式是什么意思呢?

举个例子:从本地文件中读取两个数据,相加。假设java能使用的最大并行数为8,读取数据用了1秒,cpu计算相加用了1秒

从本地文件中读取数据并不是cpu干的事,cpu计算相加用了一秒,因此最合适的线程池大小就是

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ssm基于vue的大学生社团管理系统的设计与实现+vue论文

基于vue的大学生社团管理系统的设计与实现 计算机科学与技术 2022届 姓名 学号 摘要 当下&#xff0c;正处于信息化的时代&#xff0c;许多行业顺应时代的变化&#xff0c;结合使用计算机技术向数字化、信息化建设迈进。传统的大学生社团信息管理模式&#xff0c;采用人工登…

【Vue2+3入门到实战】(13)插槽<slot>详细示例及自定义组件的创建与使用代码示例 详解

目录 一、学习目标1.插槽2.综合案例&#xff1a;商品列表 一、插槽-默认插槽1.作用2.需求3.问题4.插槽的基本语法5.代码示例6.总结 二、插槽-后备内容&#xff08;默认值&#xff09;1.问题2.插槽的后备内容3.语法4.效果5.代码示例 三、插槽-具名插槽1.需求2.具名插槽语法3.v-s…

Apache Flink连载(二十):Flink On Yarn运行 - Yarn Per-Job模式(弃用)

🏡 个人主页:IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 🚩 私聊博主:加入大数据技术讨论群聊,获取更多大数据资料。 🔔 博主个人B栈地址:豹哥教你大数据的个人空间-豹哥教你大数据个人主页-哔哩哔哩视频 目录 1. 任务提交命令 2. 任务…

使用electron属性实现保存图片并获取图片的磁盘路径

在普通的网页开发中&#xff0c;JavaScript由于安全性的考虑&#xff0c;通常是无法直接获取到客户端的磁盘路径的。浏览器出于隐私和安全原因对此类信息进行了限制。 在浏览器环境下&#xff0c;JavaScript主要通过Web APIs来与浏览器进行交互&#xff0c;而这些API通常受到浏…

lottie 动画在 vue 中的使用

前言 最近我所负责的项目中采用了动画效果&#xff0c;最早使用 gif 来实现。然而&#xff0c;在实践过程中&#xff0c;我发现 gif 格式的动画在 git 中出现了明显的锯齿感&#xff0c;这让我非常困扰。为了追求更完美的表现效果&#xff0c;我最终选择了 lottie 来实现我的动…

C++核心编程四(继承、多态、virtual关键字、文件操作)

文章目录 继承继承方式继承中的对象模型继承中构造和析构顺序继承同名成员处理方式继承同名<静态>成员处理方式多继承语法菱形继承多态多态案例1、计算器类 纯虚函数和抽象类多态案例2、制作饮品 虚析构和纯虚析构多态案例3、电脑组装 文件写操作读文件二进制写文件二进制…

ClickHouse基础知识(四):ClickHouse 引擎详解

1. 表引擎的使用 表引擎是 ClickHouse 的一大特色。可以说&#xff0c; 表引擎决定了如何存储表的数据。包括&#xff1a; ➢ 数据的存储方式和位置&#xff0c;写到哪里以及从哪里读取数据。 默认存放在/var/lib/clickhouse/data ➢ 支持哪些查询以及如何支持。 ➢ 并发数…

CUDA驱动深度学习发展 - 技术全解与实战

全面介绍CUDA与pytorch cuda实战 关注TechLead&#xff0c;分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验&#xff0c;同济本复旦硕&#xff0c;复旦机器人智能实验室成员&#xff0c;阿里云认证的资深架构师&#xff0c;项目管理专业人士&…

【SD】保持图片大小 精细化处理 高清放大

首先开启 ADetailer可以修复手部&#xff0c;脸部&#xff0c;全身。 生成一张图片。 best quality,masterpiece,simple_white_background,golden and white theme,Sense of coordination,sense of order,mathematics beauty,(((cover design))),(((((cover art))))),((trim)),…

喜讯!云起无垠获评ISC 2023数字安全创新能力百强双料大奖

近日&#xff0c;第四届数字安全“奥斯卡”——ISC 2023数字安全创新能力百强评选活动在北京圆满闭幕。本次活动旨在挖掘和孵化数字安全领域的“专精特新”力量&#xff0c;共同推进数字中国的安全建设。 在本次评选中&#xff0c;云起无垠凭借其在软件供应链安全领域的创新实…

SpringBoot 3.2.0 结合Redisson接入Redis

依赖版本 JDK 17 Spring Boot 3.2.0 Redisson 3.25.0 工程源码&#xff1a;Gitee 集成Redis步骤 导入依赖 <properties><redisson.version>3.25.0</redisson.version> </properties> <dependencies><dependency><groupId>org.pr…

Vue3-30-路由-嵌套路由的基本使用

什么是嵌套路由 嵌套路由 &#xff1a;就是一个组件内部还希望展示其他的组件&#xff0c;使用嵌套的方式实现页面组件的渲染。 就像 根组件 通过路由渲染 普通组件一样&#xff0c;嵌套路由也是一样的道理。 嵌套路由的相关关键配置 1、<router-view> 标签 声明 被嵌套组…

Echarts中饼图-实现放大显示数据

示例 代码演示 option {tooltip: {trigger: item},legend: {top: 5%,left: center},series: [{name: Access From,type: pie,radius: [40%, 70%],avoidLabelOverlap: false,label: {show: false,position: center},emphasis: {scale: true,//是否开启高亮后扇区的放大效果。s…

python查找mongo中符合条件的json记录

一、需求&#xff1a; 之前有次需要临时查找mongo中存储的json串&#xff0c;符合特定条件的记录&#xff1b; 举个例子&#xff0c;mongo中记录如下图&#xff1a; 其中每条存储的数据大概为&#xff1a; [{"createUser": "Zxtech","paramName&qu…

LVM逻辑卷与扩容

目录 一.LVM&#xff1a; 1.什么是LVM&#xff1a; 2.LVM的基本核心组件&#xff1a; 3.LVM的基本命令&#xff1a; 二.逻辑卷的创建&#xff1a; 第一步&#xff0c;我们先要为虚拟机添加硬盘 然后我们要添加依赖包 然后我们要进行磁盘分区 再添加好分区后&#xff0…

回顾2023,展望2024

时光飞逝&#xff0c;光阴似箭&#xff0c;转眼间又到了一年的年末&#xff0c;现在是2023年12月29日&#xff0c;再过两天就要元旦了&#xff0c;我们也要跨入2024年了。 记录自己的总结&#xff0c;一直想写&#xff0c;不知从何写起&#xff0c;在这一年中&#xff0c;有深夜…

程序员实现财富自由的十种方法!

程序员肯定都有过一夜暴富的梦想&#xff0c;也许是兼职接单&#xff0c;也许是成为炙手可热的大网红&#xff0c;也许只是平凡的中张百万大奖彩票…… 除去运气超好实力拔群以外&#xff0c;大多数程序员是很难在短时间内实现财富自由的。虽是如此&#xff0c;但搞钱对于程序…

Unity Shader-真实下雨路面

Unity Shader-真实下雨路面 简介素材1.准备插件Amplify Shader Editor&#xff08;这里我使用的是1.6.4最新版&#xff09;2.贴纸和切图d 一、创建一个Shader Surface&#xff0c;实现气泡播放效果二、叠加一次气泡播放效果&#xff0c;使其看起来更多&#xff0c;更无序三、小…

Matplotlib_plt.subplots 遇见中文乱码解决方案

文章目录 一、现象&#xff1a;二、解决方案1.将 **SimHei.ttf** &#xff0c;下载到当前运行目录中2.绘图中涉及标题、横纵坐标等&#xff0c;加上 **FontProperties font** 即可 环境说明&#xff1a;macOS系统 一、现象&#xff1a; 原先代码是这样的 import numpy as n…

BUUCTF Reverse/[2019红帽杯]Snake

BUUCTF Reverse/[2019红帽杯]Snake 下载解压缩后得到可执行文件&#xff0c;而且有一个unity的应用程序&#xff0c;应该是用unity编写的游戏 打开是一个贪吃蛇游戏 用.NET Reflector打开Assembly-CSharp.dll。&#xff08;unity在打包后&#xff0c;会将所有的代码打进一个Ass…