(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 {@Overridepublic 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 {@Overridepublic 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计算相加用了一秒,因此最合适的线程池大小就是

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

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

相关文章

获取拼多多商品详情页数据SKU价格等

拼多多根据ID取商品详情 API 返回值说明 item_get-根据ID取商品详情 pinduoduo.item_get 响应参数 请求测试链接 名称类型必须示例值描述 num_iid String01999629976商品ID title String02019新款女装短袖t恤女夏宽松韩版休闲上衣百搭蝙蝠衫五分袖体恤商品标题 price Flo…

Ubuntu安装K8S(1.28版本,基于containrd)

原文网址&#xff1a;Ubuntu安装K8S(1.28版本&#xff0c;基于containrd&#xff09;-CSDN博客 简介 本文介绍Ubuntu安装K8S的方法。 官网文档&#xff1a;这里 1.安装K8S 1.让apt支持SSL传输 sudo apt-get update sudo apt-get -y install apt-transport-https ca-certi…

mysqlCPU超过100%的详细解决过程

前段时间我的一个网站经常打不开,通过检查发现服务器cpu占用超过100%,通过top命令发现是mysql占用cpu特别高导致的,下面这篇文章主要给大家介绍了关于mysql占用CPU超过100%的详细解决过程,需要的朋友可以参考下 一、使用top命令看到的情况如下&#xff1a; 可以看到服务器负载…

spring security oauth2搭建认证服务器

如图&#xff08;上面图片的代码在业务项目中&#xff09;&#xff0c;第一步在独立的业务项目中&#xff0c;先获取授权码&#xff08;也叫jsessionId&#xff09;、获取授权码的路径就是 /oauth2/authorize&#xff0c;这个路径是oauth2的框架中被OAuth2AuthorizationEndpoin…

tcp 乱序度量与丢包标记

传统 tcp 以序列号差度量乱序&#xff0c;比如 1, 2, 3, 4, 6, 7, 8, 5 这个序列的 5 延后了 3 个段&#xff0c;就称这个序列的乱序度为 3。 如果乱序度为 m&#xff0c;则序列 n, n 1 k, n 1 k r, …, n 1 k r x 中&#xff0c;只要 (n 1 k r x) - (n 1) k …

vmware虚拟机中Nat、桥接模式和仅主机的差别

NAT 在NAT模式下&#xff0c;主机3是Kali和Win两个操作系统的宿主机&#xff0c;那么Kali和Win可以连接到外网&#xff0c;也可以和主机3进行互联&#xff0c;但是主机1和主机2不能连接到Kali和Win。 桥接 在桥接模式下&#xff0c;主机3是Kali和Win两个操作系统的宿主机&…

Javascript知识点锦集

【版权声明】未经博主同意&#xff0c;谢绝转载&#xff01;&#xff08;请尊重原创&#xff0c;博主保留追究权&#xff09; https://blog.csdn.net/m0_69908381/article/details/135165704 出自【进步*于辰的博客】 文章目录 1、其他知识点链接7、关于 false8、关于 null 与 …

【开源学习】ThingsBoard -- 基本配置与使用

【开源学习】ThingsBoard -- 基本配置与使用 租户及客户管理租户及租户账号管理租户管理租户创建租户修改租户删除 租户账号管理租户账号创建租户账号修改租户账号删除 客户及客户账号管理客户管理客户创建客户修改客户删除 客户用户管理客户用户创建客户用户修改客户用户删除 …

WPF+Halcon 培训项目实战(6):目标匹配助手

文章目录 前言相关链接项目专栏模板匹配助手简单使用金字塔级别参数自动选择应用插入代码 总结 前言 为了更好地去学习WPFHalcon&#xff0c;我决定去报个班学一下。原因无非是想换个工作。相关的教学视频来源于下方的Up主的提供的教程。这里只做笔记分享&#xff0c;想要源码…

2236. 判断根结点是否等于子结点之和 23.12.28(一)

给你一个 二叉树 的根结点 root&#xff0c;该二叉树由恰好 3 个结点组成&#xff1a;根结点、左子结点和右子结点。 如果根结点值等于两个子结点值之和&#xff0c;返回 true &#xff0c;否则返回 false 。 示例 1&#xff1a; 输入&#xff1a;root [10,4,6] 输出&#xf…

ssm基于JavaWeb的校园心理健康网站的设计与实现论文

摘 要 如今的时代&#xff0c;是有史以来最好的时代&#xff0c;随着计算机的发展到现在的移动终端的发展&#xff0c;国内目前信息技术已经在世界上遥遥领先&#xff0c;让人们感觉到处于信息大爆炸的社会。信息时代的信息处理肯定不能用之前的手工处理这样的解决方法&#x…

QT应用篇 二、QML用Image组件实现Progress Bar 的效果

QT应用篇 一、QT上位机串口编程 二、QML用Image组件实现Progress Bar 的效果 三、QML自定义显示SpinBox的加减按键图片及显示值效果 文章目录 QT应用篇前言一、qml需求二、使用组件1.Image组件2.Image中fillMode的使用例子 总结 前言 记录自己学习QML的一些小技巧方便日后查找…

openGauss学习笔记-176 openGauss 数据库运维-实例主备切换

文章目录 openGauss学习笔记-176 openGauss 数据库运维-实例主备切换176.1 操作场景176.2 操作步骤176.3 示例176.4 错误排查176.5 异常处理 openGauss学习笔记-176 openGauss 数据库运维-实例主备切换 176.1 操作场景 openGauss在运行过程中&#xff0c;数据库管理员可能需要…

Arduino stm32 USB CDC虚拟串口使用示例

Arduino stm32 USB CDC虚拟串口使用示例 &#x1f4cd;相关篇《STM32F401RCT6基于Arduino框架点灯程序》&#x1f516;本开发环境基于VSCode PIO&#x1f33f;验证芯片&#xff1a;STM32F401RC⌛USB CDC引脚&#xff1a; PA11、 PA12&#x1f527;platformio.ini配置信息&…

爬虫工作量由小到大的思维转变---<第三十三章 Scrapy Redis 23年8月5日后会遇到的bug)>

前言: 收到回复评论说,按照我之前文章写的: 爬虫工作量由小到大的思维转变---&#xff1c;第三十一章 Scrapy Redis 初启动/conn说明书)&#xff1e;-CSDN博客 在启动scrapy-redis后,往redis丢入url网址的时候遇到: TypeError: ExecutionEngine.crawl() got an unexpected …

归并算法:分治而治的高效算法大揭秘(图文详解)

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《数据结构&算法》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! &#x1f4cb; 前言 归并算法是我们算法中最常见的算法之一&#xff0c;其思想非常巧妙。本身归并是只能归并有序数组…

Java企业电子招投标系统源代码,支持二次开发,采用Spring cloud框架

在数字化采购领域&#xff0c;企业需要一个高效、透明和规范的管理系统。通过采用Spring Cloud、Spring Boot2、Mybatis等先进技术&#xff0c;我们打造了全过程数字化采购管理平台。该平台具备内外协同的能力&#xff0c;通过待办消息、招标公告、中标公告和信息发布等功能模块…

C# WPF上位机开发(WebApi联调)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 很多时候&#xff0c;客户需要开发的不仅仅是一个上位机系统&#xff0c;它还有其他很多配套的系统或设备&#xff0c;比如物流小车、立库、数字孪…

助力城市部件[标石/电杆/光交箱/人井]精细化管理,基于YOLOv7【tiny/yolov7】开发构建生活场景下城市部件检测识别系统

井盖、店杆、光交箱、通信箱、标石等为城市中常见部件&#xff0c;在方便居民生活的同时&#xff0c;因为后期维护的不及时往往会出现一些“井盖吃人”、“线杆、电杆、线缆伤人”事件。造成这类问题的原因是客观的多方面的&#xff0c;这也是城市化进程不断发展进步的过程中难…

ssm基于JavaEE的智能实时疫情监管服务平台的设计与实现+jsp论文

摘 要 社会发展日新月异&#xff0c;用计算机应用实现数据管理功能已经算是很完善的了&#xff0c;但是随着移动互联网的到来&#xff0c;处理信息不再受制于地理位置的限制&#xff0c;处理信息及时高效&#xff0c;备受人们的喜爱。本次开发一套智能实时疫情监管服务平台有管…