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

news2024/11/11 8:03:24

池化技术

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

Java线程池核心原理

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

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

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

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

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

Tomcat自定义线程池

    // 自定义的线程队列 最大值是 Integer.MAX_VALUE;
   taskqueue = new TaskQueue(maxQueueSize);
   // 自定义线程工厂,名称是tomcat-exec- (所以这就是为什么日志中是打印的它)
   TaskThreadFactory tf = new TaskThreadFactory(namePrefix,daemon,getThreadPriority());
   // 自定义线程池
   // 最小线程数 20 最大线程数 200  空闲时间 60S
   executor = 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) {
        // 执行一个任务加1
        submittedCount.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)) {
                        // 执行失败 -1
                        submittedCount.decrementAndGet();
                        // //如果缓冲队列也满了,插入失败,执行拒绝策略。
                        throw new RejectedExecutionException(sm.getString("threadPoolExecutor.queueFull"));
                    }
                } catch (InterruptedException x) {
                    //  // 执行失败 -1
                    submittedCount.decrementAndGet();
                    throw new RejectedExecutionException(x);
                }
            } else {
                //  // 执行失败 -1
                submittedCount.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 checks
        if (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.coloradmin.cn/o/1925561.html

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

相关文章

springboot个人健康信息管理小程序-计算机毕业设计源码

摘要 在当今这个数字化、信息化的时代&#xff0c;个人健康管理已成为人们生活中不可或缺的一部分。随着生活节奏的加快&#xff0c;越来越多的人开始关注自己的身体状况&#xff0c;希望能够及时了解并调整自己的生活习惯&#xff0c;以达到最佳的健康状态。为此&#xff0c;我…

Codeforces Round 957 (Div. 3) D,F

D. Test of Love 很容易想到dp&#xff0c;对于dp的转移方程也比较好写&#xff0c;当前点只能从当前点前面m个点转移过来&#xff0c;那么思考转移的条件&#xff0c;对于前面的点 j j j &#xff0c;如果 j j j 是水并且 i i i 和 j j j 不相邻&#xff0c;那么不能进行转…

初始化列表和explicit关键字和static成员

初始化列表 1.初始化和赋值的概念&#xff1a; 首先我们先来了解一下成员变量初始化和赋值的概念&#xff0c;初始化是是对成员变量进行一次赋值&#xff0c;注意是只能一次赋值&#xff0c;而赋值是可以多次进行赋值的。 2.初始化列表的引出&#xff1a; 我们知道了初始化…

ftp pool 功能分析及 golang 实现

本文探究一种轻量级的 pool 实现 ftp 连接。 一、背景 简要介绍&#xff1a;业务中一般使用较多的是各种开源组件&#xff0c;设计有点重&#xff0c;因此本文探究一种轻量级的 pool 池的思想实现。 期望&#xff1a;设置连接池最大连接数为 N 时&#xff0c;批量执行 M 个 F…

Transformer模型:Decoder的self-attention mask实现

前言 这是对Transformer模型Word Embedding、Postion Embedding、Encoder self-attention mask、intra-attention mask内容的续篇。 视频链接&#xff1a;20、Transformer模型Decoder原理精讲及其PyTorch逐行实现_哔哩哔哩_bilibili 文章链接&#xff1a;Transformer模型&…

【JVM实战篇】内存调优:内存泄露危害+内存监控工具介绍+内存泄露原因介绍

文章目录 内存调优内存溢出和内存泄漏内存泄露带来什么问题内存泄露案例演示内存泄漏的常见场景场景一场景二 解决内存溢出的方法常用内存监控工具Top命令优缺点 VisualVM软件、插件优缺点监控本地Java进程监控服务器的Java进程&#xff08;生产环境不推荐使用&#xff09; Art…

JavaWeb(三:JDBC 与 MVC)

JavaWeb&#xff08;一&#xff1a;基础知识和环境搭建&#xff09;https://blog.csdn.net/xpy2428507302/article/details/140365130?spm1001.2014.3001.5501JavaWeb&#xff08;二&#xff1a;Servlet与Jsp&#xff0c;监听器与过滤器&#xff09;https://blog.csdn.net/xpy…

Python蜂窝通信Wi-Fi和GPU变分推理及暴力哈希加密协议图消息算法

&#x1f3af;要点 &#x1f3af;图模型和消息传递推理算法 | &#x1f3af;消息传递推理和循环消息传递推理算法 | &#x1f3af;空间人工智能算法多维姿势估计 | &#x1f3af;超图结构解码算法量子计算 | &#x1f3af;GPU处理变分推理消息传递贝叶斯网络算法 | &#x1f3…

5G-A通感融合赋能低空经济-RedCap芯片在无人机中的应用

1. 引言 随着低空经济的迅速崛起&#xff0c;无人机在物流、巡检、农业等多个领域的应用日益广泛。低空飞行器的高效、安全通信成为制约低空经济发展的关键技术瓶颈。5G-A通感一体化技术通过整合通信与感知功能&#xff0c;为低空网络提供了强大的技术支持。本文探讨了5G-A通感…

【中国近代史】林则徐虎门销烟(1839年)

中国古代朝代历史经过两周时间&#xff08;7.03-7.13&#xff09;的分享已经正式结束&#xff0c;首先感谢大家通过那个专栏点赞收藏关注我&#xff0c;这是我继续创作的动力。 接下来新的专栏就是中国近代史。让我们再次走入近代史的潮流中&#xff0c;去学习去感受先辈们的拼…

计组_多处理器的基本概念

2024.06.26&#xff1a;计算机组成原理多处理器的基本概念学习笔记 第21节 多处理器的基本概念 1. 计算机体系结构1.1 SISD单指令流单数据流&#xff08;前面几章一直在学习的内容&#xff09;1.2 SIMD单指令流多数据流1.2.1 改进&#xff1a;向量处理器 1.3 MISD多指令流单数据…

应用帕累托原则学习新的编程语言

在本文中&#xff0c;我将讨论如何应用帕累托原则快速学习一门新的编程语言&#xff0c;并在加深对编程语言的理解的同时开始解决实际问题。 什么是帕累托原则&#xff1f; 帕累托原则&#xff0c;又称 80/20 法则&#xff0c;指出对于许多结果而言&#xff0c;大约 80% 的后…

数据湖仓一体(一) 编译hudi

目录 一、大数据组件版本信息 二、数据湖仓架构 三、数据湖仓组件部署规划 四、编译hudi 一、大数据组件版本信息 hudi-0.14.1zookeeper-3.5.7seatunnel-2.3.4kafka_2.12-3.5.2hadoop-3.3.5mysql-5.7.28apache-hive-3.1.3spark-3.3.1flink-1.17.2apache-dolphinscheduler-3.1.9…

我的智能辅助大师-办公小浣熊

一、基本介绍 随着2022年ChatGPT为代表的AI工具对互联网领域进行第一次冲击后&#xff0c;作为一名对编程领域涉足不算特别深的一名程序员&#xff0c;对AI大模型的接触也真的不能算少了&#xff0c;这是时代的必然趋势。在此之前也曾接触过很多的AI工具&#xff0c;他们都能在…

跨境电商系统如何进行搭建

目前越来越多的商家&#xff0c;他们都在进行跨境电商建站&#xff0c;便于自己在网络上进行营销推广&#xff0c;跨境电商系统的搭建是至关重要的&#xff0c;商家应该先了解跨境电商的模式有哪些&#xff0c;这样才能对跨境电商系统有更好的搭建结果。 跨境电商模式 目前来…

1589. 【中山市第十二届义务教育段学生信息学邀请赛】象战(bishop)(Standard IO)

题目描述 国际象棋的棋盘可以表示为一个 8 行 8 列的格子图&#xff0c;其中每个格子都可以放一枚棋子。我们将第 1 行第 2 列的格子用 (1,2) 来表示&#xff0c;以此类推。 为了帮助妹妹认识国际象棋中的“象”这种棋子&#xff0c;Jimmy 可谓是煞费苦心——他首先教会妹妹&…

【Java】数据类型及类型转换

数据类型 Java语言的数据类型分为两大类&#xff1a; 基础数据类型引用数据类型 基础数据类型 基础数据类型包括以下8种&#xff1a; 类型名称关键字占用内存取值范围区间描述字节型byte1 字节-128~127-27~27-1短整型short2 字节-32768~32767-215~215-1整型int4 字节-2147…

算法学习笔记(8.3)-(0-1背包问题)

目录 最常见的0-1背包问题&#xff1a; 第一步&#xff1a;思考每轮的决策&#xff0c;定义状态&#xff0c;从而得到dp表 第二步&#xff1a;找出最优子结构&#xff0c;进而推导出状态转移方程 第三步&#xff1a;确定边界条件和状态转移顺序 方法一&#xff1a;暴力搜素…

经典元启发式算法的适用范围及基本思想

元启发式算法是针对优化问题设计的一类高级算法&#xff0c;它们具有广泛的适用性&#xff0c;可以解决不同类型的问题。不同的元启发式算法由于其特定的搜索机制和策略&#xff0c;适用的优化问题类型也有所不同。以下是一些常见元启发式算法及其适用范围&#xff1a; 1. 遗传…

OrangePi AIpro 浅上手及搭建卡通图像生成多元化AI服务

前言 很高兴&#xff0c;收到了一份新款 OrangePi AIpro 开发板&#xff0c;这是香橙派第一次与华为昇腾合作&#xff0c;使用昇腾系列 AI 处理器来设计这款高性价比的 AI 开发板。这块开发板不仅性能强大&#xff0c;还支持丰富的硬件接口&#xff0c;为AI开发者提供了一个理…