【JUC】线程池ThreadPoolTaskExecutor与面试题解读

1、ThreadPoolTaskExecutor 创建线程池

从它的创建和使用说起,创建和使用的代码如下:
创建:

   ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(corePoolSize);executor.setMaxPoolSize(maxPoolSize);executor.setQueueCapacity(queueCapacity);executor.setKeepAliveSeconds(keepAliveSeconds);executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());executor.setThreadNamePrefix("ExecutorPool-");executor.initialize();return executor;

使用:

 threadPoolTaskExecutor.execute(() -> {//do something...});

上面创建线程池使用的是ThreadPoolTaskExecutor ,点击进入executor.initialize()方法:
ExecutorConfigurationSupport.java

	/*** Set up the ExecutorService.*/public void initialize() {if (logger.isInfoEnabled()) {logger.info("Initializing ExecutorService" + (this.beanName != null ? " '" + this.beanName + "'" : ""));}if (!this.threadNamePrefixSet && this.beanName != null) {setThreadNamePrefix(this.beanName + "-");}this.executor = initializeExecutor(this.threadFactory, this.rejectedExecutionHandler);}

再进入initializeExecutor方法:
ThreadPoolTaskExecutor.java

	/*** Note: This method exposes an {@link ExecutorService} to its base class* but stores the actual {@link ThreadPoolExecutor} handle internally.* Do not override this method for replacing the executor, rather just for* decorating its {@code ExecutorService} handle or storing custom state.*/@Overrideprotected ExecutorService initializeExecutor(ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {BlockingQueue<Runnable> queue = createQueue(this.queueCapacity);ThreadPoolExecutor executor;if (this.taskDecorator != null) {executor = new ThreadPoolExecutor(this.corePoolSize, this.maxPoolSize, this.keepAliveSeconds, TimeUnit.SECONDS,queue, threadFactory, rejectedExecutionHandler) {@Overridepublic void execute(Runnable command) {Runnable decorated = taskDecorator.decorate(command);if (decorated != command) {decoratedTaskMap.put(decorated, command);}super.execute(decorated);}};}else {executor = new ThreadPoolExecutor(this.corePoolSize, this.maxPoolSize, this.keepAliveSeconds, TimeUnit.SECONDS,queue, threadFactory, rejectedExecutionHandler);}if (this.allowCoreThreadTimeOut) {executor.allowCoreThreadTimeOut(true);}this.threadPoolExecutor = executor;return executor;}
ThreadPoolExecutor  executor = new ThreadPoolExecutor(corePoolSize,maxPoolSize,keepAliveSeconds,TimeUnit.SECONDS,queue, threadFactory,rejectedExecutionHandler);

可以看到new ThreadPoolExecutor(),ThreadPoolTaskExecutor 本质是使用ThreadPoolExecutor,那为何要存在ThreadPoolTaskExecutor?
ThreadPoolTaskExecutor的方法基本都是围绕如何创建ThreadPoolExecutor,安全有效设置各种参数,添一些行为等。
在这里插入图片描述
如下面设置MaxPoolSize(最大线程池数),它考虑到并发同步、threadPoolExecutor 是否为null的问题。
ThreadPoolTaskExecutor.java

/*** Set the ThreadPoolExecutor's maximum pool size.* Default is {@code Integer.MAX_VALUE}.* <p><b>This setting can be modified at runtime, for example through JMX.</b>*/
public void setMaxPoolSize(int maxPoolSize) {synchronized (this.poolSizeMonitor) {this.maxPoolSize = maxPoolSize;if (this.threadPoolExecutor != null) {this.threadPoolExecutor.setMaximumPoolSize(maxPoolSize);}}
}

再如:
设置队列时,它会创建一个安全的队列,有合适大小的LinkedBlockingQueue或者没有大小的SynchronousQueue。从而避免使用newSingleThreadExecutor这类创建一个不安全的等待队列。
ThreadPoolTaskExecutor.java

/*** Create the BlockingQueue to use for the ThreadPoolExecutor.* <p>A LinkedBlockingQueue instance will be created for a positive* capacity value; a SynchronousQueue else.* @param queueCapacity the specified queue capacity* @return the BlockingQueue instance* @see java.util.concurrent.LinkedBlockingQueue* @see java.util.concurrent.SynchronousQueue*/
protected BlockingQueue<Runnable> createQueue(int queueCapacity) {if (queueCapacity > 0) {return new LinkedBlockingQueue<>(queueCapacity);}else {return new SynchronousQueue<>();}
}

newSingleThreadExecutor方式创建的等待队列中的LinkedBlockingQueue容量是Integer.MAX_VALUE
Executors.java

 public static ExecutorService newSingleThreadExecutor() {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));}

LinkedBlockingQueue.java

 public LinkedBlockingQueue() {this(Integer.MAX_VALUE);}

ThreadPoolTaskExecutor的父类ExecutorConfigurationSupport的方法可以设置BeanName、ThreadNamePrefix等。
在这里插入图片描述
总结来说在spring项目中使用ThreadPoolTaskExecutor创建线程池是首推使用的。

2、ThreadPoolExecutor解读

2.1 基本使用介绍

ThreadPoolExecutor  executor = new ThreadPoolExecutor(corePoolSize,maxPoolSize,keepAliveSeconds,TimeUnit.SECONDS,queue, threadFactory,rejectedExecutionHandler);
  • corePoolSize:线程池的核心线程数,定义了最小可以同时运行的线程数量。

  • maximumPoolSize:线程池的最大线程数。队列中存放的任务达到队列容量时,可以同时运行的线程数量变为最大线程数。

  • keepAliveTime:当线程池中的线程数量大于corePoolSize时,如果没有新任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了KeepAliveTime才会被回收销毁。

  • unit:keepAliveTime参数的时间单位,包括DAYS、HOURS、MINUTES、MILLISECONDS等。

  • workQueue:用于保存等待执行任务的阻塞队列。可以选择以下集个阻塞队列:

    • ArrayBlockingQueue:是一个基于数组结构的阻塞队列,此队列按FIFO原则对元素进行排序;
    • LinkedBlockingQueue:是一个基于链表结构的阻塞队列,此队列按FIFO排序元素,吞吐量通常高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列;
    • SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量常高于LinkedBlockingQueue,静态工厂方法Executors.newCachedThreadPool()使用了这个队列;
    • PriorityBlockingQueue:一个具有优先级的无限阻塞队列;
  • threadFactory:用于设置创建线程的工厂,可以通过工厂给每个创造出来的线程设置更有意义的名字。使用开源框架guava提供的ThreadFactoryBuilder可以快速给线程池里的线程设置有意义的名字:new ThreadFactoryBuilder().setNameFormat(“XX-task-%d”).build();7)handler:饱和策略。若当前同时运行的线程数量达到最大线程数量并且队列已经被放满,ThreadPoolExecutor定义了一些饱和策略:

    • ThreadPoolExecutor.AbortPolicy:直接抛出RejectedExecutionException异常来拒绝处理新任务;
    • ThreadPoolExecutor.CallerRunsPolicy:只用调用者所在的线程来运行任务,会降低新任务的提交速度,影响程序的整体性能;
    • ThreadPoolExecutor.DiscardPolicy:不处理新任务,直接丢弃掉;
    • ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列中最近的一个任务,执行当前任务;

    处理流程:

在这里插入图片描述
1.在创建了线程池之后,等待提交过来的任务请求
2.当调用execute()方法添加一个请求任务的时候,线程池会做出如下判断:
2.1 如果正在运行的线程数量小于corePoolSize,那么马上创建线程运行这个程序
2.2 如果正在运行的线程数量大于或者等于corePoolSize,那么将这个任务放入队列
2.3 如果这个时候队列满了并且正在运行的线程数量还小于maximumPoolSize,那么还是要创建非核心线程立刻执行这个任务
2.4 如果队列满了并且正在运行的线程数量大于或等于maximumPoolSize,那么线程池会启动饱和拒绝策略来执行
3. 当一个线程完成任务的时候,它会从队列中取下一个任务来执行
4. 当一个线程无事可做超过一定时间(keepAliveTime)时:线程会判断如果当前运行的线程数大于corePoolSize,那么这个线程就会被停掉。
最经典的比喻是银行办理业务,可以很形象的去理解线程池七个核心参数之间的关系:

在这里插入图片描述
银行刚开始上班,然后又一位需要办理业务的顾客1进来,柜员1就来一个帮这位顾客1办理,其他在吃早餐摸鱼。这位顾客1办理完了业务就走了,柜员1坐在柜台上静等。

这时又有一位顾客2过来,这时不是柜员1去接待,而是叫上柜员2,因为这天安排上班的两位柜员(corePoolSize=2)。

顾客3来办理业务,因为上班的柜员已经全部就位了,柜员1有空,柜员1就去接待顾客3。

顾客4来办理业务,因为柜员1和柜员2都在忙,所以顾客4在凳子上静等。柜员2帮顾客2办理完了,就去给顾客4办理。这时凳子又空出3张(Queue容量为3)。

顾客5、顾客6、顾客7同时过来,柜员1和柜员2都在忙,顾客5、顾客6、顾客7就坐满了凳子。

过了一会,顾客8来了,柜员1和柜员2在忙同时没有凳子坐了,本着顾客就是上帝的原则,打电话叫来一个在休息的柜员3帮顾客8办理业务。

生意兴隆,顾客9来了,打电话叫来一个在休息的柜员4帮顾客9办理业务。

这是顾客10来了,一进门,柜员没有了,连休息中的也没有了(maximumPoolSize=4),银行直接赶走他。

过了一段时间,银行的客户都办完业务走了,那两位本来应该休息的柜员说:我们再等一下(keepAliveTime),不忙了我们就撤了。

看上面的场景中,搬救兵请休息中的柜员回来干活是很麻烦的,要先坐满凳子再说。线程池中也是,要等等待队列满了以后才会去创建核心线程数之外的线程,因为创建线程的花销是很大的。

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

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

相关文章

Java之继承详解二

3.7 方法重写 3.7.1 概念 方法重写 &#xff1a;子类中出现与父类一模一样的方法时&#xff08;返回值类型&#xff0c;方法名和参数列表都相同&#xff09;&#xff0c;会出现覆盖效果&#xff0c;也称为重写或者复写。声明不变&#xff0c;重新实现。 3.7.2 使用场景与案例…

Spring复习:(55)ApplicationContext中BeanFactoryPostProcessor是怎么添加到容器的?

容器创建时会调用AbstractApplicationContext的refresh方法&#xff0c;其中会调用invokeBeanFactoryPostProcessor方法&#xff0c;如下图 invokeBeanFactoryPostProcessors代码如下&#xff1a; 其中调用的PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcess…

计算机竞赛 交通目标检测-行人车辆检测流量计数 - 计算机竞赛

文章目录 0 前言1\. 目标检测概况1.1 什么是目标检测&#xff1f;1.2 发展阶段 2\. 行人检测2.1 行人检测简介2.2 行人检测技术难点2.3 行人检测实现效果2.4 关键代码-训练过程 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 毕业设计…

【Flutter】Flutter 使用 font_awesome_flutter 展示图标

【Flutter】Flutter 使用 font_awesome_flutter 展示图标 文章目录 一、前言二、安装和基本使用1. 安装2. 基本使用示例3. 图标的命名和样式 三、自定义图标和高级功能1.动态检索图标2.排除样式和优化 四、完整示例五、总结 一、前言 在现代移动应用开发中&#xff0c;图标起着…

C语言入门 Day_8数据与运算小结

目录 前言 1.精度 2.运算 2.易错点 3.思维导图 前言 到目前为止我们一共学习了四种数据类型&#xff0c;他们分别是表示整数的整型&#xff1b;表示小数的浮点型&#xff1b;表示字符的字符型&#xff1b;和表示布尔数的布尔型。 表示整数的整型&#xff0c;它的变量类型名…

浅谈泛在电力物联网在电力设备状态在线监测中的应用

安科瑞 华楠 摘要&#xff1a;随着信息化水平的不断发展&#xff0c;泛在电力物联网的建设提上日程&#xff0c;这对提升变电站电力设备在线监测水平&#xff0c;推动智能电网发展具有重要的指导意义。对基于物联网的电力设备状态监测系统进行了研究&#xff0c;概括了泛在电力…

Android TV开发之VerticalGridView

Android TV应用开发和手机应用开发是一样的&#xff0c;只是多了焦点控制&#xff0c;即选中变色。 androidx.leanback.widget.VerticalGridView 继承 BaseGridView &#xff0c; BaseGridView 继承 RecyclerView 。 所以 VerticalGridView 就是 RecyclerView &#xff0c;使…

Redis高可用:哨兵机制(Redis Sentinel)详解

目录 1.什么是哨兵机制&#xff08;Redis Sentinel&#xff09; 2.哨兵机制基本流程 3.哨兵获取主从服务器信息 4.多个哨兵进行通信 5.主观下线和客观下线 6.哨兵集群的选举 7.新主库的选出 8.故障的转移 9.基于pub/sub机制的客户端事件通知 1.什么是哨兵机制&#xf…

重生之我要学C++第六天(const,static,友元)

这篇文章的主要内容是const以及权限问题、static关键字、友元函数和友元类&#xff0c;希望对大家有所帮助&#xff0c;点赞收藏评论支持一下吧&#xff01; 更多优质内容跳转&#xff1a; 专栏&#xff1a;重生之C启程(文章平均质量分93) 目录 const以及权限问题 1.const修饰…

【计算机网络】【常考问题总结】

1. ping 127.0.0.1 后会发生什么&#xff1f; ping 127.0.0.1 &#xff1b;ping 0.0.0.0 &#xff1b; ping localhost 面试官问&#xff1a;断网了&#xff0c;还能ping通 127.0.0.1 吗&#xff1f;为什么&#xff1f;_kevin_tech的博客-CSDN博客 2. MTU&#xff0c;MMU是…

新书上市----Pytest企业级应用实战 新书上市

【原文链接】新书上市----Pytest企业级应用实战 新书上市 《Pytest企业级应用实战》 京东购书链接 当当购书链接 天猫购书链接 作者简介 本书作者本硕毕业于哈尔滨工业大学&#xff0c;曾先后就职于中兴通讯和华为&#xff0c;现任职于中科南京软件技术研究院&#xff0c;…

(三)行为型模式:3、解释器模式(Interpreter Pattern)(C++示例)

目录 1、解释器模式&#xff08;Interpreter Pattern&#xff09;含义 2、解释器模式的UML图学习 3、解释器模式的应用场景 4、解释器模式的优缺点 5、C实现解释器模式的实例 1、解释器模式&#xff08;Interpreter Pattern&#xff09;含义 解释器模式&#xff08;Interp…

python分析实战(4)--获取某音热榜

1. 分析需求 打开某音热搜&#xff0c;选择需要获取的热榜如图 查找包含热搜内容的接口返回如图 将url地址保存 2. 开发 定义请求头 headers {Cookie: 自己的cookie,Accept: application/json, text/plain, */*,Accept-Encoding: gzip, deflate,Host: www.douyin.com,…

陕西科技大学改考408!附考情分析

改考信息 8月14日&#xff0c;陕西科技大学公布了2024年硕士研究生招生目录&#xff08;初稿&#xff09;&#xff0c;其中不难发现083500软件工程初试专业课由819数据结构改为408计算机学科专业基础 图片&#xff1a;陕西科技大学24专业目录-软件工程学硕 https://yjszs.sus…

优化指南:带宽限制的可行策略

大家好&#xff01;作为一名专业的爬虫程序员&#xff0c;我们经常面临的一个挑战就是带宽限制。尤其是在需要快速采集大量数据时&#xff0c;带宽限制成为了我们提升爬虫速度的一大阻碍。今天&#xff0c;我将和大家分享一些解决带宽限制的可行策略&#xff0c;希望能帮助大家…

[C++ 网络协议编程] 域名及网络地址

1. DNS服务器 DNS&#xff08;Domain Name System&#xff09;&#xff1a;是对IP地址和域名&#xff08;如:www.baidu.com等&#xff09;进行相互转换的系统&#xff0c;其核心是DNS服务器。 我们输入的www.baidu.com是域名&#xff0c;是一种虚拟地址&#xff0c;而非实际地…

C# API 文档注释规范

C# API 文档注释规范 1. 命名空间注释(namespace)2. summary3. remarks and para4. param5. returns6. example and code7. exception8. typeparam 最近在开发工作中需要实现 API 帮助文档&#xff0c;如果根据所写的代码直接重写 API 帮助文档将会是意见非常大的工作量&#x…

新版本Qt Creator无法提示错误、不报红

问题 更新新版本Qt Creator后无法实时提示错误&#xff0c;在开发中非常难受 如图&#xff0c;此时w后面少了;Qt Creator却只有红色横线标识&#xff0c;没有具体的错误。 解决方法 首先要知道&#xff0c;提供这个错误显示功能是ClangCodeModel插件提供的&#xff0c;因此…

ModaHub魔搭社区:AI Agent在操作系统场景下的AgentBench基准测试

近日,来自清华大学、俄亥俄州立大学和加州大学伯克利分校的研究者设计了一个测试工具——AgentBench,用于评估LLM在多维度开放式生成环境中的推理能力和决策能力。研究者对25个LLM进行了全面评估,包括基于API的商业模型和开源模型。 他们发现,顶级商业LLM在复杂环境中表现出…

外网连接局域网的几种方式?快解析内网穿透安全便利吗?

外网连接局域网是一项网络连接中的关键技术&#xff0c;它能够让远程用户通过互联网访问内部局域网中的资源和服务。外网连接局域网为企业提供了更大的灵活性和便捷性&#xff0c;但也需要严格的安全措施来防止未经授权的访问。 外网连接局域网的几种方式 在将外网连接到局域…