java多线程——线程池

概述

线程池是管理java线程生命周期的工具

  • 降低资源消耗。通过池化技术能够重复利用已创建的线程,降低线程频繁创建和销毁造成的资源消耗
  • 提高线程的可管理性。无需程序员手动销毁线程,控制线程创建的数量,避免无限制的创建影响系统稳定性

线程池的运行机制

线程池的核心参数

  1. corePoolSize(必需):核心线程数量。默认情况下,核心线程会一直存活,但是当allowCoreThreadTimeout 设置为true时,核心线程也会超时回收
  2. maximumPoolSize(必需):最大线程数量,当线程池内的线程数量到达该数之后,后续的新任务将交由拒绝策略处理
  3. keepAliveTime(必需):线程闲置超时时长。如果闲置线程的时间超过该时长,非核心线程就会被回收,如果allowCoreThreadTimeout 设置为true时,核心线程也会超时回收
  4. unit(必需):keepAliveTime参数的时间单位
  5. workQueue(必需):线程等待队列即任务等待的队列
  6. threadFactory(可选):线程工厂,用于指定线程池创建新线程的方式
  7. handler(可选):拒绝策略,当到达最大线程数时需要执行的拒绝策略, 默认为AbortPolicy即丢弃任务并抛异常

提交任务的流程

线程池实现类——ThreadPoolExecutor

构造方法

参数说明

ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue<Runnable> workQueue)

corePoolSize:核心线程池大小

maximumPoolSize:最大线程池大小

keepAliveTime:当线程数>核心线程数时,这是 多余线程在任务执行完成后最大的存活时间

unit:时间单位

workQueue:线程等待队列即任务等待的队列

ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue<Runnable> workQueue,

ThreadFactory threadFactory)

corePoolSize:核心线程池大小

maximumPoolSize:最大线程池大小

keepAliveTime:当线程数>核心线程数时,这是 多余线程在任务执行完成后最大的存活时间

unit:时间单位

workQueue:线程等待队列即任务等待的队列

threadFactory:线程创建工厂

ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue<Runnable> workQueue,

RejectedExecutionHandler handler)

corePoolSize:核心线程池大小

maximumPoolSize:最大线程池大小

keepAliveTime:当线程数>核心线程数时,这是 多余线程在任务执行完成后最大的存活时间

unit:时间单位

workQueue:线程等待队列即任务等待的队列

handler:拒绝执行某个线程的策略LinkedBlockingQueue

LinkedBlockingQueue<Runnable>

队列默认size=Integer.MAX_VALUE,即是一个无界队列

底层实现是链表;读和写使用的是两个不同的锁,所以是读写分离的队列。

阻塞操作:

take();//当队列中无元素时,阻塞等待

put();//当队满时阻塞等待

非阻塞操作:

poll();//当队列为null时,返回null

offer();//堆满时return false;

功能线程池

Executors已经为我们封装好了四种常见的功能线程池:

  • 定长线程池(FixedThreadPool)
  • 定时线程池(ScheduledThreadPool )
  • 可缓存线程池(CachedThreadPool)
  • 单线程化线程池(SingleThreadExecutor)

从结构图中能看到四种线程池的真正实现类是ThreadPoolExecutor

线程池类型

1、newScheduledThreadPool 调度型线程池

  • 支持定时及周期性的执行任务,提交任务时支持设置任务的调度周期
  • 只限制了核心线程数,也就是最大线程数为Integer.MAX_VALUE,当添加任务的速度大于线程池处理任务的速度,可能会创建大量的线程,消耗资源,甚至导致OOM

1.1 构造

构造方法

参数

newScheduledThreadPool(int corePoolSize)

corePoolSize:corePoolSize

maximumPoolSize:Integer.MAX_VALUE

keepAliveTime:0

unit:NANOSECONDS

workQueue:DelayedWorkQueue

newScheduledThreadPool( int corePoolSize, ThreadFactory threadFactory)

1.2 任务队列-DelayedWorkQueue

  • 该队列的数据结构是优先级队列(依赖堆实现),当新来任务时将该task插入堆并根据优先级重新调整堆,保证优先级最高的task在fist index
  • 执行任务时,获取fist index中的task,并保证等待够delay时间后再执行(当fist task执行后也需要重新调整堆)

2、newCachedThreadPool 缓存型线程池

  • 无核心线程数,无非核心线程数,执行完闲置60s回收,任务队列为不存储元素的阻塞队列
  • 适用于短期异步的小任务,或负载较轻的服务器
  • 创建的最大线程数为Integer.MAX_VALUE,当添加任务的速度大于线程池处理任务的速度,可能会创建大量的线程,消耗资源,甚至导致OOM

2.1 构造方法

构造方法

参数

ExecutorService newCachedThreadPool()

参数默认值

corePoolSize:0

maximumPoolSize:Integer.MAX_VALUE

keepAliveTime:60L

unit:TimeUnit.SECONDS

workQueue:SynchronousQueue<Runnable>

ExecutorService newCachedThreadPool(ThreadFactory threadFactory)

2.2 任务队列-SynchronousQueue

  • 队列是不存储元素缓存队列的,每次要进行offer操作时必须等待poll操作,否则不能继续添加元素
  • 当前线程A执行offer操作将task添加到queue中,若没有另一个线程来消费该task,那线程A会一直阻塞直到另一个线程来消费该task

3、newFixedThreadPool

  • 创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程
  • 适用于限制当前线程数量的应用场景,适用于负载比较重的服务器
  • 创建了一个无界队列LinkedBlockingQueuesize,是一个最大值为Integer.MAX_VALUE的线程阻塞队列,当添加任务的速度大于线程池处理任务的速度,可能会在队列堆积大量的请求,消耗很大的内存,甚至导致OOM

3.1 构造方法

构造方法

参数

ExecutorService newFixedThreadPool(int nThreads)

corePoolSize:nThreads

maximumPoolSize:nThreads

keepAliveTime:0L

unit:TimeUnit.MILLISECONDS,

workQueue:LinkedBlockingQueue<Runnable>

threadFactory

ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory)

3.2 任务队列-LinkedBlockingQueue<Runnable>

  • 队列默认size=Integer.MAX_VALUE即是一个无界队列,底层实现是链表,当添加任务的速度大于线程池处理任务的速度,可能会在队列堆积大量的请求,消耗很大的内存,甚至导致OOM
  • 读和写使用的是两个不同的锁,所以是读写分离的队列

4、SingleThreadExecutor

  • 创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务,如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它
  • 此线程池保证所有任务的执行顺序按照任务的提交顺序执行

4.1 构造方法

构造方法

参数

ExecutorService newSingleThreadExecutor()

corePoolSize:1

maximumPoolSize:1

keepAliveTime:0L

unit:TimeUnit.MILLISECONDS,

workQueue:LinkedBlockingQueue<Runnable>

threadFactory

ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory)

4.2 任务队列-LinkedBlockingQueue<Runnable>

  • 队列默认size=Integer.MAX_VALUE即是一个无界队列,底层实现是链表,当添加任务的速度大于线程池处理任务的速度,可能会在队列堆积大量的请求,消耗很大的内存,甚至导致OOM
  • 读和写使用的是两个不同的锁,所以是读写分离的队列

线程池拒绝策略:

实现java.util.concurrent.RejectedExecutionHandler接口

1,CallerRunsPolicy:当想提交任务的线程池还存活,就由提交task的当前线程来执行

2,AbortPolicy:丢弃任务并抛出RejectedExecutionException异常,(默认拒绝策略)

3,DiscardPolicy:丢弃任务但是不抛异常

4,DiscardOldestPolicy:当想提交任务的线程池还存活,就将丢弃队列最前面的任务,然后重新提交被拒绝的任务

对比

类型

池内线程数量

任务队列

特点

应用场景

newScheduledThreadPool

核心线程:固定

非核心线程:无限制

DelayedWorkQueue

  1. 定时,周期性执行

执行定时/周期性任务

newCachedThreadPool

无限制

SynchronousQueue

  1. 无最大线程数限制
  2. 队列不存储元素,当没有空闲线程时会立即新建线程
  3. 当添加任务的速度大于线程池处理任务的速度,可能会创建大量的线程,消耗资源,甚至导致OOM

执行数量多,耗时少的线程任务

newFixedThreadPool

固定

LinkedBlockingQueue

  1. 每来一个任务就会新建线程,直到线程数到达指定的数量
  2. 核心线程数处于空闲状态也不会被回收,除非线程关闭
  3. 当所有线程都处于活跃状态,新的任务都会处于等待状态,直到有线程空闲出来
  4. 任务队列无限制

控制线程的最大并发数

newSingleThreadExecutor

1个

LinkedBlockingQueue

  1. 保证所有任务按照指定顺序在一个线程中方执行
  2. 不需要处理线程同步的问题

单线程

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

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

相关文章

OpenHarmony上移植memtester

1. 下载源码&#xff1a; wget https://pyropus.ca./software/memtester/old-versions/memtester-4.6.0.tar.gz 2. 解压并指定交叉编译方式 解压 tar -xvf memtester-4.6.0.tar.gz 修改conf-cc和conf-ld&#xff0c;指定交叉编译方式 conf-cc conf-ld 3. 编译 直接运行m…

Stable Diffusion入门使用技巧及个人实例分享--大模型及lora篇

大家好&#xff0c;近期使用Stable Diffusion比较多&#xff0c;积累整理了一些内容&#xff0c;得空分享给大家。如果你近期正好在关注AI绘画领域&#xff0c;可以看看哦。 本文比较适合已经解决了安装问题&#xff0c;&#xff08;没有安装的在文末领取&#xff09; 在寻找合…

分布式搜索——ElasticSeach简介

一般都用数据库存储数据&#xff0c;然后对数据库进行查询获取数据&#xff0c;但是当数据量很大时&#xff0c;查询效率就会很慢&#xff08;具体下面会讲到&#xff09;&#xff0c;所以这种情况下就会使用到ElasticSeach ElasticSeach的基本介绍 ElasticSeach是一 款非常强…

杰发科技AC7801——ADC之Bandgap和内部温度计算

0. 参考 电流模架构Bandgap设计与仿真 bandgap的理解&#xff08;内部带隙电压基准&#xff09; ​ ​ 虽然看不懂这些公式&#xff0c;但是比较重要的一句应该是这个&#xff1a;因为传统带隙基准的输出值为1.2V ​ 1. 使用 参考示例代码。 40002000是falsh控制器寄…

NXP RT1176(一)——二级BootLoader开发(安全引导加载程序SBL)

目录 1. 开发环境 2. 二级BOOT的功能 3. 步骤 3.1 配置源码 3.2 构建项目 3.2.1 MDK 3.2.2 IAR&#xff08;IAR也编译一下工程看看&#xff0c;这样两个平台都可以支持了&#xff09; 单核M7的开发&#xff01;&#xff01; 1. 开发环境 本文Windows下开发&#xff1a;…

MHD、MQA、GQA注意力机制详解

MHD、MQA、GQA注意力机制详解 注意力机制详解及代码前言&#xff1a;MHAMQAGQA 注意力机制详解及代码 前言&#xff1a; 自回归解码器推理是 Transformer 模型的 一个严重瓶颈&#xff0c;因为在每个解码步骤中加 载解码器权重以及所有注意键和值会产生 内存带宽开销 下图为三…

【合成孔径雷达】合成孔径雷达的多视角理解和时/频成像算法的统一解释

文章目录 一、什么是雷达成像&#xff08;1&#xff09;主要的遥感探测手段&#xff1a;光学、红外和雷达&#xff08;2&#xff09;从数学的角度&#xff1a;雷达成像主要研究什么&#xff1f;数据采集&#xff1a; y T x n yTxn yTxn信息提取&#xff1a; y − > x ? y…

编译错误:stray ‘\357’ in program的解决方法

目录 把报错文件更换编码格式&#xff0c;我试的utf-8 bom编码就可以了&#xff0c;可以多换几种试试。 网友的另一种案例&#xff1a; 编译错误&#xff1a;stray ‘\357’ in program的解决方法 把报错文件更换编码格式&#xff0c;我试的utf-8 bom编码就可以了&#xff0c…

如何同步管理1000个设备的VLAN数据?

什么是VLAN&#xff1f; VLAN&#xff0c;也就是虚拟局域网&#xff0c;是通过为子网提供数据链路连接来抽象出局域网的概念。在企业网中&#xff0c;一个企业级交换机一般是24口或者是48口&#xff0c;连接这些接口的终端在物理上形成一个广播域。广播域过大&#xff0c;就会导…

【AI智能体】零代码构建AI应用,全网都在喊话歌手谁能应战,一键AI制作歌手信息查询应用

欢迎来到《小5讲堂》 这是《文心智能体平台》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 文心智能体大赛背景创建应用平台地址快速构建【基础配置】…

前端无样式id或者class等来定位标签

目录&#xff1a; 1、使用背景2、代码处理 1、使用背景 客户使用我们产品组件&#xff0c;发现替换文件&#xff0c;每次替换都会新增如下的样式&#xff0c;造就样式错乱&#xff0c;是组件的文件&#xff0c;目前临时处理的话就是替换文件时删除新增的样式&#xff0c;但是发…

【JVM】阅读Class字节码:常量池

目录 基本结构解析 常量池 常量池简介 如何阅读Class文件中的常量池信息 基本结构解析 Magic(魔数) Magic的唯一作用是确定这个文件是否为一个能被虚拟机所接受的class 文件。魔数值固定为0xCAFEBABE&#xff0c;不会改变。 常量池 常量池简介 下图是反编译过后的字节码文…

TensorFlow的学习

0.基础概念 术语表&#xff1a; https://developers.google.cn/machine-learning/glossary?hlzh-cn#logits 1.快速入门 https://tensorflow.google.cn/tutorials/quickstart/beginner?hlzh-cn 2.基于Keras进行图像分类 https://tensorflow.google.cn/tutorials/keras/cl…

gradle 共享存储挂载缓存目录的问题

2个任务同时构建的时候&#xff0c;报错如上。 原因&#xff1a;挂载目录的问题导致的&#xff0c;挂在最小粒度的目录下。 /home/app/.gradle/caches/modules-2/files-2.1 挂载到这个级别的目录下。

演员怎么上百度百科

百度百科是一个公正、开放、客观的平台&#xff0c;它为演员提供了一个展示自己过往经历和演艺生涯的平台。以下是百科优化网yajje总结的演员创建百度百科的一些步骤和注意事项&#xff1a; 创建演员百度百科的基本条件 人物影响力&#xff1a;演员创建百度百科需要满足官方的规…

振弦采集仪在岩土工程监测中的重要性及应用案例分享

振弦采集仪在岩土工程监测中的重要性及应用案例分享 岩土工程监测是为了确保土地和建筑物的稳定性以及确保施工安全而进行的一项重要工作。河北稳控科技振弦采集仪是岩土工程监测中一种常用的仪器设备&#xff0c;通过测量土体振动频率来评估土体的稳定性和强度变化&#xff0…

霸道龙尊短视频:成都鼎茂宏升文化传媒公司

霸道龙尊短视频&#xff1a;龙族的传奇与现代的交融 在数字化时代的浪潮中&#xff0c;短视频以其短小精悍、内容丰富的特点&#xff0c;迅速占领了人们的碎片时间。成都鼎茂宏升文化传媒公司而在这些短视频中&#xff0c;一股独特的“霸道龙尊”风潮正在悄然兴起&#xff0c;…

Nginx配置文件conf解释

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 Nginx(“engine x”…

基于springboot+vue+Mysql的在线答疑系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

服务攻防——应用协议软件,设备平台

向日葵利用 vnc利用5900端口 当为none就可以直接连接&#xff0c;而其他几种密码也能破解 可以使用hydna来尝试爆破 teamviewer(cve2020-13699) 让对方点击这个网站&#xff0c;就会 触发 zabbix 端口10051 cve2020 手工 点击这个 找到cookie 然后不需要密码就能进…