线程进阶-1 线程池

一.说一下线程池的执行原理

1.线程池的七大核心参数

(1)int corePoolSize:核心线程数。默认情况下核心线程会一直存活,当设置allowCoreThreadTimeout为true时,核心线程也会被超时回收。

(2)int maximumPoolSize:线程池能容纳的最大线程数。maximumPoolSize = 核心线程数 + 救急线程数。

(3)long keepAliveTime:线程闲置的超时时长。当线程闲置超时时,此线程会被回收,释放资源。超时回收默认情况下只针对救急线程。

(4)TimeUnit unit:keepAliveTime的时间单位,如TimeUnit.MILLISECONDS、TimeUnit.SECONDS等。

(5)BlockingQueue<Runnable> workQueue:任务队列。当核心线程数都被占用时,新提交的任务会被放到任务队列中等待。

(6)ThreadFactory threadFactory:线程工厂,为可选参数。

        a.ThreadFactory为一个接口,只提供一个newThread()方法,传入一个Runnable对象,返回一个执行该Runnable的Thread对象。用于定制线程对象的创建。

        b.若未指定ThreadFactory,则线程池会使用默认的ThreadFactory——只是创建Thread执行Runnable,不对线程作额外的处理。

(7)RejectedExecutionHandler handler:拒绝策略,为可选参数

        a.当核心线程、救急线程都被占用,且任务队列已满时,会对新提交的任务执行拒绝策略。

        b.若未指定拒绝策略,则线程池会默认使用AbortPolicy

2.线程池的拒绝策略

(1)AbortPolicy:丢弃新任务,并抛出异常。

(2)DiscardPolicy:丢弃新任务,但不会抛出异常。

(3)DiscardOldestPolicy:丢弃任务队列队头的任务,将新任务插入到任务队列队尾。

(4)CallerRunsPolicy:让调用者线程自己来执行任务。即如果当前线程A向线程池提交了一个任务,且该任务触发了线程池的CallerRunsPolicy拒绝策略,则线程池会将该任务退回给线程A,让线程A来执行该任务。

(5)自定义拒绝策略:实现RejectedExecutionHandler接口,并重写rejectedExecution()方法。

3.线程池的执行原理

对于新提交的任务:

(1)判断核心线程是否有空闲,若有空闲则交由核心线程执行。若核心线程都被占用,则继续判断

(2)判断等待队列是否有空位,若有空位则插入到队尾。若等待队列已满,则继续判断

(3)判断救急线程是否有空闲,若有空闲则交由救急线程执行。若救急线程都被占用,则执行拒绝策略

补充:

(1)核心线程和救急线程每执行完一个任务,都会再去等待队列中取待执行任务继续执行。若等待队列中没有任务,则默认情况下,核心线程进入空闲状态,救急线程开始闲置超时的计时。

(2)当核心线程都被占用且等待队列已满时,才会创建救急线程来执行新任务。被创建的救急线程,会直接忽视等待队列的任务,先去执行新提交的任务;等到新任务执行完,才会开始执行等待队列的任务。

二.线程池中常见的任务队列

1.ArrayBlockingQueue:基于数组结构的有界阻塞队列,任务执行顺序为FIFO

2.LinkedBlockingQueue:基于链表结构的有界阻塞队列,任务执行顺序为FIFO

3.DelayedWorkQueue:是一个优先级队列。在提交任务时可以指定当前任务需要延时多长时间后才执行,DelayedWorkQueue的任务执行顺序为当前队列中指定执行时间最早的任务。

4.SynchronousQueue:不存储元素的阻塞队列。每个线程的插入操作都需要等待另一个线程的移除操作,是线程和线程间的传递。

三.说一下ArrayBlockingQueue和LinkedBlockingQueue的区别

1.底层数据结构

(1)ArrayBlockingQueue底层是数组

(2)LinkedBlockingQueue底层是单向链表

2.容量

(1)ArrayBlockingQueue是强制有界,创建时需要传入一个int值作为容量

(2)LinkedBlockingQueue是默认无界,支持有界。默认容量为Integer.MAX_VALUE,创建时可以传入一个int值作为容量。

3.加锁方式

ArrayBlockingQueue和LinkedBlockingQueue都是使用ReentrantLock加锁。

(1)ArrayBlockingQueue的插入和删除操作都是只加一把锁,同时锁住入队和出队。

(2)LinkedBlockingQueue插入操作锁尾节点,不锁头节点;删除操作锁头节点,不锁尾节点。即在执行入队时可以出队,执行出队时可以入队,效率更高。

四.线程池的execute()和submit()方法的区别

线程池可以通过execute()或submit()方法来提交任务

1.执行对象不同

(1)execute(Runnable command):该方法用于执行Runnable接口的任务

(2)submit(Callable<T> task)、submit(Runnable task)、submit(Runnable task,T result):submit()的三个重载方法表明其既可以执行Callable接口任务也可以执行Runnable接口任务。传入的Runnable接口在内部会先被转化为Callable接口再作为任务执行,因此submit()方法最终的执行对象都是Callable接口。

2.返回值不同

(1)execute()方法执行对象是Runnable接口任务,Runnable的run()方法没有返回值,因此execute()方法也没有返回值。execute()主要用于执行不需要返回结果的任务。

(2)submit()方法最终执行对象都是Callable接口任务,其返回值为Future<T>,可以调用Future的get()方法获取任务执行后的返回值。

3.异常处理不同

(1)execute()提交的任务在执行中遇到异常时,会将异常传递给线程的UncaughtExceptionHandler处理,默认是直接将异常抛出。

(2)submit()提交的任务在执行中遇到异常时,仅仅是停止执行任务,但不会将异常立即抛出,相当于暂时吞掉异常;直到外部调用Future的get()方法尝试获取任务执行的返回值时,才会将异常抛出。即允许延迟处理异常。

五.线程池有哪几种状态?

1.RUNNING:线程池的初态,代表线程池正在处理和接收任务。

2.SHUTDOWN:调用shutdown()方法会进入此状态。表明线程池不再接收新任务,但会继续处理已经提交到等待队列的任务。

3.STOP:调用shutdownNow()方法会进入此状态。表明线程池不再接收新任务,也不会再处理等待队列中的任务,同时还会尝试中断正在执行的任务。

4.TIDYING:过渡态,当线程池的所有任务都已经终止(无论是正常执行完还是通过取消或异常终止),并且所有工作线程都关闭,就会进入此状态。该状态下,线程池会执行terminated()钩子方法。

5.TERMINATED:最终态。当terminated()方法执行完就会进入此状态,代表线程池完全终止。

六.线程池的种类有哪些?

Executors类提供了创建多种线程池的静态方法,常见的有4种:

1.newFixedThreadPool:固定线程数的线程池。

(1)核心线程数=最大线程数,无救急线程。

(2)任务队列为LinkedBlockingQueue,容量为默认的Integer.MAX_VALUE。

(3)适用于任务量已知,相对耗时的任务。

2.newSingleThreadPool:单线程化的线程池。

(1)核心线程数=最大线程数=1,作为唯一的工作线程;无救急线程。

(2)任务队列为LinkedBlockingQueue,容量为默认的Integer.MAX_VALUE。

(3)适用于按照顺序执行的任务。

3.newCachedThreadPool:可缓存线程

(1)核心线程数=0,最大线程数=救急线程数=Integer.MAX_VALUE,即全为救急线程在工作,因此可以灵活创建、回收线程。

(2)任务队列为SynchronousQueue

(3)适用于任务数比较密集,但每个任务执行时间较短的情况。

4.newScheduledThreadPoolExecutor:具有延迟和周期执行功能的线程池。

(1)核心线程数自定义,最大线程数=Integer.MAX_VALUE。

(2)任务队列为DelayedWorkQueue,使用schedule()提交任务,指定任务的延时执行时间。

七.为什么不建议使用Executors类提供的方法创建线程?

1.FixedThreadPool和SignalThreadPool都允许任务队列的长度为Integer.MAX_VALUE,可能会堆积大量的任务请求,导致OOM。

2.newCachedThreadPool和newScheduledThreadPool的最大线程数都为Integer.MAX_VALUE,可能会创建大量的线程,导致OOM。

八.如何控制某个方法允许并发访问线程的数量?

1.使用newFixedThreadPool,但有OOM的风险。

2.使用Semaphore类,每一个线程访问该方法都acquire()获取一个信号量,若信号量数大于0,则该线程获取到一个信号量,信号量数减1;若信号量数小于0,则该线程阻塞;若线程执行完该方法,则release()释放一个信号量,信号量数加1。

九.如何确定线程池的核心线程数?

假设cpu的核数为N

1.对于高并发、执行时间短的任务:需要减少线程数以减少线程上下文切换带来的消耗。因此核心线程数设置为N+1。

2.对于并发不高、任务执行时间长的任务:

(1)IO密集型任务:例如文件读写、DB读写、网络请求等,不需要占用过多cpu。核心线程数设置为2N+1。

(2)cpu密集型任务:例如计算型代码、Bitmap转换、Gson转换等,需大量占用cpu,需要减少线程数以减少线程上下文切换带来的消耗。因此核心线程数设置为N+1。

十.说一下线程池的使用场景

1.数据批量导出

(1)使用线程池+CountDownLatch批量将数据库中的数据导出,避免OOM。

(2)场景:例如使用分页查询去导出数据库中的数据,线程池的每个线程负责一页数据的导出,并发执行,每有一个线程执行完,CountDownLatch减一,直到所有线程执行完,CountDownLatch等于零,主线程才继续执行。

2.数据汇总

(1)如果一个请求要调用多个接口来汇总数据,且接口间没有依赖关系,则可以使用线程池+Future获取调用结果的方式来并发执行,提升性能。

3.异步线程

(1)为了避免下一级方法影响上一级方法响应时间,可以使用异步线程并发调用下一级方法(前提是不需要下一级方法的返回值),提高响应速率。

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

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

相关文章

Linux基础指令磁盘管理001

Linux磁盘管理涉及多个方面&#xff0c;包括硬盘分区、文件系统创建、挂载、检查磁盘空间、优化性能和维护等。今天我们讲一下磁盘的分区挂载&#xff0c;文件系统的创建。 操作系统 CentOS Stream 9 磁盘的分区 当我们新插入一块磁盘后&#xff0c;首先使用fdisk -l查看磁盘…

实战经验分享之移动云快速部署Stable Diffusion SDXL 1.0

本文目录 前言产品优势部署环境准备模型安装测试运行 前言 移动云是中国移动面向政府、企业和公众的新型资源服务。 客户以购买服务的方式&#xff0c;通过网络快速获取虚 拟计算机、存储、网络等基础设施服务&#xff1b;软件开发工具、运行环境、数据库等平台服务&#xff1…

【评价类模型】熵权法

1.客观赋权法&#xff1a; 熵权法是一种客观求权重的方法&#xff0c;所有客观求权重的模型中都要有以下几步&#xff1a; 1.正向化处理&#xff1a; 极小型指标&#xff1a;取值越小越好的指标&#xff0c;例如错误率、缺陷率等。 中间项指标&#xff1a;取值在某个范围内较…

[ubuntu18.04]搭建mptcp测试环境说明

MPTCP介绍 Multipath TCP — Multipath TCP -- documentation 2022 documentation 安装ubuntu18.04&#xff0c;可以使用虚拟机安装 点击安装VMware Tool 桌面会出现如下图标 双击打开VMware Tools&#xff0c;复制如下图所示的文件到Home目录 打开终端&#xff0c;切换到管…

[Linux]重定向

一、struct file内核对象 struct file是在内核中创建&#xff0c;专门用来管理被打开文件的结构体。struct file中包含了打开文件的所有属性&#xff0c;文件的操作方法集以及文件缓冲区&#xff08;无论读写&#xff0c;我们都需要先将数据加载到文件缓冲区中。&#xff09;等…

基于JSP的高校二手交易平台

开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;JSP技术 工具&#xff1a;浏览器&#xff08;如360浏览器、谷歌浏览器、QQ浏览器等&#xff09;、MySQL数据库 系统展示 系统功能界面 用户注册与登录界面 个人中心界面 商品信息界面 摘要 本文研究了高…

C#中的数组探索

在C#编程语言中&#xff0c;数组是一种基本的数据结构&#xff0c;用于存储固定大小的同类型元素序列。本文将深入探讨C#数组的各个方面&#xff0c;包括定义、赋值、范围操作、切片、多维数组&#xff08;矩形与锯齿形&#xff09;、简化初始化表达式以及边界检查。 数组定义…

为何懂行的人都在选海信Mini LED?

今年的618大促比往年来得要更早一些。纵览各电商平台的电视产品&#xff0c;能发现Mini LED电视的出镜率很高&#xff0c;成了各大品牌的主推产品。 对于什么样的Mini LED更值得买&#xff0c;各品牌都有自己的说辞。因为缺乏科学系统的选购标准&#xff0c;消费者容易在各方说…

【Qt】【模型-视图架构】代理模型示例

文章目录 1. 基本排序/过滤模型Basic Sort/Filter Model Example2. 自定义排序/过滤模型Custom Sort/Filter Model ExampleFilterLineEdit类定义及实现MySortFilterProxyModel类定义及实现 1. 基本排序/过滤模型Basic Sort/Filter Model Example 官方提供的基本排序/过滤模型示…

docker镜像体积优化攻略参考—— 筑梦之路

简单介绍 镜像的本质是镜像层和运行配置文件组成的压缩包&#xff0c;构建镜像是通过运行 Dockerfile 中的 RUN 、COPY 和 ADD 等指令生成镜像层和配置文件的过程。 和镜像体积大小有关的关键点&#xff1a; RUN、COPY 和 ADD 指令会在已有镜像层的基础上创建一个新的镜像层&…

【数据结构】详解二叉树

文章目录 1.树的结构及概念1.1树的概念1.2树的相关结构概念1.3树的表示1.4树在实际中的应用 2.二叉树的结构及概念2.1二叉树的概念2.2特殊的二叉树2.2.1满二叉树2.2.2完全二叉树 2.3 二叉树的性质2.4二叉树的存储结构2.4.1顺序结构2.4.2链表结构 1.树的结构及概念 1.1树的概念…

基于SSM的车辆租赁管理系统(含源码+sql+视频导入教程)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于SSM的车辆租赁管理系统1拥有两种角色 管理员&#xff1a;用户管理、用户租车、用户换车和车辆入库、添加汽车、添加客户、生成出租单、客户选车、出租单管理、查询出租单、角色权限管…

代码随想录算法训练营第三十四 |● 1005.K次取反后最大化的数组和 ● 134. 加油站 ● 135. 分发糖果

今天的解析写在了代码注释中 1005.K次取反后最大化的数组和 讲解链接&#xff1a;https://programmercarl.com/1005.K%E6%AC%A1%E5%8F%96%E5%8F%8D%E5%90%8E%E6%9C%80%E5%A4%A7%E5%8C%96%E7%9A%84%E6%95%B0%E7%BB%84%E5%92%8C.html class Solution { public:static bool cmp(i…

登录校验及全局异常处理器

登录校验 会话技术 会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束.在一次会话中可以包含多次请求和响应会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话请求间共享数据会话跟踪方案 客户端…

关于MD5

首先还是介绍一下关于md5的基本信息&#xff1a; MD5&#xff08;Message Digest Algorithm 5&#xff09;是一种常用的哈希函数&#xff0c;用于产生128位&#xff08;16字节&#xff09;的哈希值&#xff0c;通常以32个十六进制数字表示。MD5广泛用于计算文件或文本数据的校…

分享一个 ASP.NET Web Api 上传和读取 Excel的方案

前言 许多业务场景下需要处理和分析大量的数据&#xff0c;而 Excel 是业务人员常用的数据表格工具&#xff0c;因此&#xff0c;将 Excel 表格中内容上传并读取到网站&#xff0c;是一个很常见的功能&#xff0c;目前有许多成熟的开源或者商业的第三方库&#xff0c;比如 NPO…

香港电讯荣获经济通「金融科技大奖」专业认可

香港电讯非常荣幸在《经济通》举办的「2023金融科技大奖」中脱颖而出&#xff0c;获「杰出跨境数码方案」、「杰出网络安全方案&#xff08;商用&#xff09;」和「杰出ESG解决方案」三个重要奖项。 香港电讯拥有丰富的经验及庞大的专业技术团队&#xff0c;一直致力为客户提供…

Spring Security3.0版本

前言&#xff1a; 核心&#xff1a; A >> &#xff1f; >> B &#xff1f;代表判断层&#xff0c;由Security实现 这是之前的版本浓缩&#xff0c;现在3.0版本添加了更匹配的内容描写&#xff0c;匹配了mvc模式 非mvc模式 核心&#xff1a;client&#x…

IService 接口中定义的常用方法

文心一言生成 以下是一些 IService 接口中定义的常用方法&#xff08;以你提供的 UserSQL 类为例&#xff0c;该类继承自 ServiceImpl&#xff0c;因此也会拥有这些方法&#xff09;&#xff1a; 插入&#xff08;新增&#xff09; boolean save(T entity): 插入一条记录&…

scp:Linux系统本地与远程文件传输命令

scp 是Linux系统中用于在本地主机和远程主机之间进行文件传输的命令。 详细说明&#xff1a; scp 命令用于安全地将文件从一个主机传输到另一个主机&#xff0c;所有传输数据都是加密的。语法&#xff1a; scp [参数] [源文件路径] [目标主机:目标路径] 参数说明&#xff1a…