【tomcat】Tomcat如何扩展Java线程池原理

池化技术

在后端中,对于经常使用池化就是来提升系统性能,比如数据库连接池、线程池连接池等,本质都是利用空间换时间的来提升性能,用来避免资源的频繁创建和销毁,以此提高资源的复用率,所以合理设置系统所需的线程池大小非常重要,一般都需要结合线程启动监控系统来观察,查看设置的是否合理。但是也有缺点,那就是如何无脑的设置,可能会占用过多的内存。所以要避免出现空间过度使用出现内存泄露和频繁垃圾回收的问题。

Java线程池核心原理

在这里插入图片描述
不清楚线程池工作原理的,可以看如下文章,从使用到源码解析。

【源码解析】聊聊线程池 实现原理与源码深度解析(一)

【源码解析】聊聊线程池 实现原理与源码深度解析(二)

【Java并发】聊聊线程池原理以及实际应用

【Java并发】聊聊创建线程池的几种方式以及实际生产如何应用

Tomcat自定义线程池

    // 自定义的线程队列 最大值是 Integer.MAX_VALUE;taskqueue = new TaskQueue(maxQueueSize);// 自定义线程工厂,名称是tomcat-exec- (所以这就是为什么日志中是打印的它)TaskThreadFactory tf = new TaskThreadFactory(namePrefix,daemon,getThreadPriority());// 自定义线程池// 最小线程数 20 最大线程数 200  空闲时间 60Sexecutor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), maxIdleTime, TimeUnit.MILLISECONDS,taskqueue, tf);

可以看到 上面在初始化线程池的时候,创建了一个自定义线程队列以及一个线程工厂。

tomcat自定义线程处理流程

这里对着执行流程进行梳理下,
1.前corePoolSize个任务时,就创建核心线程处理
2.再来任务,就放入任务队列中让所有线程去抢,队列满了,创建临时线程执行。
3.达到最大线程maxNumPoolSize, 继续尝试把任务添加到任务队列中。
4.缓冲队列也满了,插入失败,执行拒绝策略。

我们看具体的code实现,可以发现,先调用java原生线程池执行,超过maximumPoolSize,java原生线程池抛出拒绝策略。尝试放入任务队列中,如果失败,抛出异常。

    public void execute(Runnable command, long timeout, TimeUnit unit) {// 执行一个任务加1submittedCount.incrementAndGet();try {// 调用java原生线程池的execute去执行任务super.execute(command);} catch (RejectedExecutionException rx) {// 如果线程数达到最大 maximumPoolSize  Java原生线程池执行拒绝策略if (super.getQueue() instanceof TaskQueue) {final TaskQueue queue = (TaskQueue)super.getQueue();try {// //继续尝试把任务放到任务队列中去if (!queue.force(command, timeout, unit)) {// 执行失败 -1submittedCount.decrementAndGet();// //如果缓冲队列也满了,插入失败,执行拒绝策略。throw new RejectedExecutionException(sm.getString("threadPoolExecutor.queueFull"));}} catch (InterruptedException x) {//  // 执行失败 -1submittedCount.decrementAndGet();throw new RejectedExecutionException(x);}} else {//  // 执行失败 -1submittedCount.decrementAndGet();throw rx;}}}

tomcat自定义任务队列

从如下代码中可以看到,自定义了一个任务队列,因为这个队列是一个无界队列,达到核心线程后,就无法创建线程,直接将任务阻塞到队列中。所以通过 submittedCount.incrementAndGet(); submittedCount.decrementAndGet(); 记录当前已经提交到线程池,但是还没有执行完的任务个数。

在任务队列的长度无限制的情况下,让线程池有机会创建新的线程。
当然默认情况下Tomcat的任务队列是没有限制的,你可以通过设置maxQueueSize参数来限制任务队列的长度。

public class TaskQueue extends LinkedBlockingQueue<Runnable> {// 构造方法 调用父类构造方法public TaskQueue(int capacity) {super(capacity);}@Override// 线程池调用任务队列的方法时,当前线程数肯定已经大于核心线程数了public boolean offer(Runnable o) {//we can't do any checksif (parent==null) return super.offer(o);//we are maxed out on threads, simply queue the object// //如果线程数已经到了最大值,不能创建新线程了,只能把任务添加到任务队列。if (parent.getPoolSize() == parent.getMaximumPoolSize()) return super.offer(o);//we have idle threads, just add it to the queue//执行到这里,表明当前线程数大于核心线程数,并且小于最大线程数。//表明是可以创建新线程的,那到底要不要创建呢?分两种情况://1. 如果已提交的任务数小于当前线程数,表示还有空闲线程,无需创建新线程if (parent.getSubmittedCount()<=(parent.getPoolSize())) return super.offer(o);//if we have less threads than maximum force creation of a new thread//2. 如果已提交的任务数大于当前线程数,线程不够用了,返回false去创建新线程if (parent.getPoolSize()<parent.getMaximumPoolSize()) return false;//if we reached here, we need to add it to the queue//默认情况下总是把任务添加到任务队列return super.offer(o);}
}

在这里插入图片描述

在这里插入图片描述

小总结

虽然面试中,对于线程池的问题很多,但是如果我们可以结合tomcat自定义线程池的原理来进行复补充,那么不仅可以体现我们对框架内部理解的深度,也可以提升对八股文的应用能力。

tomcat是如何设计的,其实主要就是继承原生ThreadPoolExecutor,重写execute(), 定制自己的任务处理流程。

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

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

相关文章

大语言模型诞生过程剖析

过程图如下 &#x1f4da; 第一步&#xff1a;海量文本的无监督学习 得到基座大模型&#x1f389; &#x1f50d; 原料&#xff1a;首先&#xff0c;我们需要海量的文本数据&#xff0c;这些数据可以来自互联网上的各种语料库&#xff0c;包括书籍、新闻、科学论文、社交媒体帖…

Object.assign方法有什么用?超详细测试用例、实例、可以在浏览器的控制台打印结果

Object.assign 是一个 JavaScript 方法&#xff0c;用于将一个或多个源对象的所有可枚举属性复制到目标对象中。它返回目标对象。这个方法常用于合并对象或浅复制对象。 语法 Object.assign(target, ...sources)target: 目标对象。sources: 一个或多个源对象。 示例 1. 合并…

【2024最新】C++扫描线算法介绍+实战例题

扫描线介绍&#xff1a;OI-Wiki 【简单】一维扫描线&#xff08;差分优化&#xff09; 网上一维扫描线很少有人讲&#xff0c;可能认为它太简单了吧&#xff0c;也可能认为这应该算在差分里&#xff08;事实上讲差分的文章里也几乎没有扫描线的影子&#xff09;。但我认为&am…

简单搭建卷积神经网络实现手写数字10分类

搭建卷积神经网络实现手写数字10分类 1.思路流程 1.导入minest数据集 2.对数据进行预处理 3.构建卷积神经网络模型 4.训练模型&#xff0c;评估模型 5.用模型进行训练预测 一.导入minest数据集 MNIST--->raw--->test-->(0,1,2...) 10个文件夹 MNIST--->raw-…

VRRP虚拟路由冗余技术

VRRP虚拟路由冗余技术&#xff1a;是一种路由容错协议&#xff0c;用于在网络中提供路由器的冗余备份。它通过将多个路由器虚拟成一个虚拟路由器并且多个路由器之间共享一个虚拟IP地址来实现冗余和高可用性。当承担转发业务的主路由器出现故障时&#xff0c;其他备份路由器可以…

git的下载流程,及使用方法,官网地址怎么找?

要下载git以及了解使用方法&#xff0c;可以按照以下步骤进行操作&#xff1a; 打开浏览器&#xff0c;输入git的官方网站地址&#xff1a;https://git-scm.com/&#xff08;官网地址可能会有变动&#xff0c;请根据最新情况进行搜索&#xff09;。 在官网上找到下载按钮或链接…

安全防御:防火墙概述

目录 一、信息安全 1.1 恶意程序一般会具备一下多个或全部特点 1.2 信息安全五要素&#xff1a; 二、了解防火墙 2.1 防火墙的核心任务 2.2 防火墙的分类 2.3 防火墙的发展历程 2.3.1 包过滤防火墙 2.3.2 应用代理防火墙 2.3.3 状态检测防火墙 补充防御设备 三、防…

uniapp微信小程序授权登录实现

我们在做小程序的时候用的最多的方式登录 就是原生的授权登录的功能 这个方法 也不是很难 首先我们要获取我们在小程序中的code值 我们小封装一个获取code 的方法 在页面中可以直接调用 封装在 js 中 export const wxlogin () > {return new Promise((resolve, reject…

骑士人才系统74cms专业版实现本地VUE打包和在线升级方法以及常见问题

骑士人才系统我就不多说了目前来说我接触的人才系统里面除了phpyun就是骑士人才了&#xff0c;两个历史都很悠久&#xff0c;总起来说功能方面各分伯仲&#xff0c;前几期我作过Phpyun的配置教程这次我们针对骑士人才系统说说怎么使用VUE源码本地一键打包后台和在线升级方式&am…

展开说说:Android之View基础知识解析

View虽不属于Android四代组件&#xff0c;但应用程度却非常非常广泛。在Android客户端&#xff0c;君所见之处皆是View。我们看到的Button、ImageView、TextView等等可视化的控件都是View&#xff0c;ViewGroup是View的子类因此它也是View。但是现在我们把View和ViewGroup当成两…

每日Attention学习10——Scale-Aware Modulation

模块出处 [ICCV 23] [link] [code] Scale-Aware Modulation Meet Transformer 模块名称 Scale-Aware Modulation (SAM) 模块作用 改进的自注意力 模块结构 模块代码 import torch import torch.nn as nn import torch.nn.functional as Fclass SAM(nn.Module):def __init__…

redisTemplate报错为nil,通过redis-cli查看前缀有乱码

public void set(String key, String value, long timeout) {redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);} 改完之后 public void set(String key, String value, long timeout) {redisTemplate.setKeySerializer(new StringRedisSerializer()…

设计模式--工厂设计模式

什么是工厂模式&#xff1f; 工厂模式是一种创建型设计模式&#xff0c;它定义了一个用于创建对象的接口&#xff0c;但由子类决定要实例化的类是哪一个。这样&#xff0c;工厂方法模式让类的实例化延迟到子类。通过工厂方法模式&#xff0c;我们可以在不修改现有代码的情况下…

opencascade AIS_InteractiveContext源码学习8 trihedron display attributes

AIS_InteractiveContext 前言 交互上下文&#xff08;Interactive Context&#xff09;允许您在一个或多个视图器中管理交互对象的图形行为和选择。类方法使这一操作非常透明。需要记住的是&#xff0c;对于已经被交互上下文识别的交互对象&#xff0c;必须使用上下文方法进行…

数据湖仓一体(五)安装spark

上传安装包到/opt/software目录并解压 [bigdatanode106 software]$ tar -zxvf spark-3.3.1-bin-hadoop3.tgz -C /opt/services/ 重命名文件 [bigdatanode106 services]$ mv spark-3.3.1-bin-hadoop3 spark-3.3.1 配置环境变量 [bigdatanode106 ~]$ sudo vim /etc/profile…

最优化(10):牛顿类、拟牛顿类算法

4.4 牛顿类算法——介绍了经典牛顿法及其收敛性&#xff0c;并介绍了修正牛顿法和非精确牛顿法&#xff1b; 4.5 拟牛顿类算法——引入割线方程&#xff0c;介绍拟牛顿算法以及拟牛顿矩阵更新方式&#xff0c;然后给出了拟牛顿法的全局收敛性&#xff0c;最后介绍了有限内存BFG…

Java中创建线程的方式

文章目录 创建线程ThreadRunnableCallable线程池创建方式自定义线程池线程池工作原理阻塞队列线程池参数合理配置线程池参数 创建线程 在Java中创建一个线程&#xff0c;有且仅有一种方式&#xff0c;创建一个Thread类实例&#xff0c;并调用它的start方法。 Thread 最经典也…

在Linux上设置MySQL允许远程连接的完整指南

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…

构建图像金字塔遍历不同的大小

1、首先、构建金字塔&#xff0c;其中包括从原始图像到多层缩小后的图像。 import cv2# 读取原始图像 image cv2.imread(path_to_image)# 构建高斯金字塔 gaussian_pyramid [image] for i in range(6): # 这里假设构建6层image cv2.pyrDown(image) # 下采样gaussian_p…

【Linux】多线程_6

文章目录 九、多线程7. 生产者消费者模型生产者消费者模型的简单代码结果演示 未完待续 九、多线程 7. 生产者消费者模型 生产者消费者模型的简单代码 Makefile&#xff1a; cp:Main.ccg -o $ $^ -stdc11 -lpthread .PHONY:clean clean:rm -f cpThread.hpp&#xff1a; #i…