tigase源码学习杂记-IO处理的线程模型
前言
tigase是一个高性能的服务器,其实个人认为作为即时通讯的服务器,高性能主要体现在他对IO复用,和多线程的使用上,今天来学习一下他的IO的线程处理模型的源码,并记录一下他优秀的设计。
概述
tigase是使用的NIO作为自己的IO模型。IOService是实现了Callable接口的并持有SocketChannel对象的一个抽象的IO封装对象。
tigase的IO处理线程模型的核心类是 SocketThread,此类提供了两个核心的静态方法:addSocketService(IOService<?> s) 和 removeSocketService(IOService<Object> s) 分别是表示把IOService对象添加进线程模型中和把IOService对象移除线程模型中。其他IO监听器类监听到IO的xmppStreamOpened()发生之后,调用addSocketService(IOService<?> s)方法将数据添加到SocketThread之后,就开始了整个多线程处理整个IO复用的流程。
IO处理流程设计
tiagase IO处理流程图
ConnectionOpenThread作为整个tigase的IO监听连接的线程,tigase服务启动之后就会启动ConnectionOpenThread。启动完ConnectionOpenThread流程如下:
- ConnectionOpenThread首先会初始化内部的Selector用于对客户端的连接的监听。(当然ConnectionOpenThread也会做一些限流的控制,超过连接数就拒绝新连接等)对应图中1步
- 接着ConnectionOpenThread就会循环监听就绪的SelectKey,拿到SocketChannel传递给ConnectionOpenListener。对应图中2、3、4步
- ConnectionOpenListener监听器就会创建IOService对象,并设置一些参数,包括SSL容器,和其他的一些监听器。对应图中5、6步
- ConnectionManager(连接管理器)启动IOService对象,添加连接超时需要执行的Task,并将IOService对象通过SocketThread.addSocketService(IOService<?> s)添加到IO复用的线程模型中,自此进入了IO处理的线程的逻辑。对应图中7、8、9步
- SocketThread.addSocketService(IOService<?> s)通过哈希和取模的算法,将数据负载均衡到不同的SocketThread的waitting的跳表集合中进行数据的缓冲。SocketThread循环从waitting跳表集合中拿到IOService并根据读写事件类型,将IOService注册到SocketThread自身的Selector对象上。对应图中10步
- SocketThread循序监听Selector就绪的SelectKey,并拿到IOService对象,并将IOService添加到forCompletion跳表集合中进行缓冲。对应图中11步
- SocketThread循环从forCompletion跳表集合中拿到IOService对象,丢到completionService线程池进行执行IOService的call()方法。对应图中12步
- ResultsListener 结果监听器线程循环监听completionService执行结束的IOService对象的状态,如果IOService状态是isConnected就继续调用SocketThread.addSocketService(IOService<?> s)添加到SocketThread进行重复调用每个IOService自身的call()方法。自此整个IO的循环处理流程基本结束。对应图中13步
SocketThread的线程模型
tigase的线程模型和Netty的主从React的模式有点像,ConnectionOpenThread主要用来处理客户端的连接建立,建立之后创建将SocketChannel封装到IOService抽象对象中,通过IOService.hashCode() % SocketThread.length 算法负载均衡到不同的ScoketThread中(因为是跟IOService计算的hash,保证相同的IO对象会添加到相同的线程中去),通过SocketChannel的一列缓冲操作,将就绪的IOServices丢到CompletionService线程池中去,线程池来执行IOService.call()方法对数据进行读写的各种操作。call()中加了读写锁,这里效率略低于Netty的设计,Netty是一个线程基于责任链的形式一个线程执行到底的无锁设计,这里ResultsListener可以将IOService再次丢入线程池中供不同的线程继续调用。
SocketThread类数据结构设计源码分析
数据结构
class SocketThread implements Runnable{//线程池private static CompletionService<IOService<?>> completionService = null;//读线程数组private static SocketThread[] socketReadThread = null;//写线程数组private static SocketThread[] socketWriteThread = null;
}
SocketThread线程通过持有两个static类型的读写线程组和CompletionService的线程池组成他的独特的线程模型,通过读写线程分组提高代码的效率,并更好地体现了设计的单一职责。CompletionService的线程池主要的作用就是解耦执行和结果的获取。采用static的类变量,就只有初始化一次。在类加载完成之后,线程处理模型就初始化好了。
初始化相关代码
class SocketThread implements Runnable{ //默认每个核心的线程数public static final int DEF_MAX_THREADS_PER_CPU = 8;//获取系统的核心数private static int cpus = Runtime.getRuntime().availableProcessors();static {if (socketReadThread == null) {//根据CPU核数计算默认线程数int nThreads = (cpus * DEF_MAX_THREADS_PER_CPU) / 2 + 1;executor = new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());completionService = new ExecutorCompletionService<IOService<?>>(executor);socketReadThread = new SocketThread[nThreads];socketWriteThread = new SocketThread[nThreads];//读线程初始化for (int i = 0; i < socketReadThread.length; i++) {socketReadThread[i] = new SocketThread("socketReadThread-" + i);socketReadThread[i].reading = true;Thread thrd = new Thread(socketReadThread[i]);thrd.setName("socketReadThread-" + i);thrd.start();}...//写线程初始化for (int i = 0; i < socketWriteThread.length; i++) {socketWriteThread[i] = new SocketThread("socketWriteThread-" + i);socketWriteThread[i].writing = true;Thread thrd = new Thread(socketWriteThread[i]);thrd.setName("socketWriteThread-" + i);thrd.start();}...} }
}
线程模型初始化很简单,就是通过一个static代码块,初始化相关的读写线程组和处理IOService的call()方法调用的线程池。这里稍微核心一点的我想说可能就是计算线程池的公式,这里对tiagse的计算公式进行化简可得 nThread = CPU 核数 * 4 + 1,而对比《java并发编程实战》一书的第八章的线程池的最优计算公式:线程数 = CPU 核数 * CPU利用率 * (1 + 等待时间/计算时间), 朝着tigase公式的形式化简一下可得:线程数 = CPU 核数 * CPU利用率 + CPU 核数 *(CPU利用率*等待时间/计算时间)),由于tigase是IO密集型系统,所以我大胆假设 CPU 核数 * CPU利用率 ≈1,所以以上两个公式可得出:CPU利用率*等待时间/计算时间 = 4.当然这这只是个人的一些假设,用于复习一下线程池计算公式。实际数据肯定是tigase经过大量测试优化之后的最优数据。
SocketThread成员变量数据结构设计源码
class SocketThread implements Runnable{//selector对象private Selector clientsSel = null;// 控制selector为空的一个计数器private int empty_selections = 0;//“待完成”的IOService的缓冲跳表集合private ConcurrentSkipListSet<IOService<?>> forCompletion = new ConcurrentSkipListSet<IOService<?>>(new IOServiceComparator());//读状态private boolean reading = false;//写状态private boolean writing = false;//停止状态private boolean stopping = false;//等待的IOService的缓冲跳表集合private ConcurrentSkipListSet<IOService<?>> waiting = new ConcurrentSkipListSet<IOService<?>>(new IOServiceComparator());
}
- clientsSel对象: 用于监听对象的就绪状态。
- empty_selections:作为一个计数器,作用是统计 “Selector中就绪的Key为0 且 waiting跳表中的IOService为0” 的个数,当个数大于默认的10次,就重新创建Selector,代码的注释写的是解决两个java的BUG,这里就不做展开。
- forCompletion:待完成的IOService的跳表缓冲集合
- reading: 标记SocketThread是否是处理IO读的线程
- writing::标记SocketThread是否是处理IO写的线程
- stopping: 标记SocketThread线程是否是已经停止
- waiting:等待的IOService的跳表缓冲集合
核心的addSocketService、 removeSocketService方法源码
/*** 核心方法添加IOService* @param s*/public static void addSocketService(IOService<?> s) {//设置IOService已就绪s.setSocketServiceReady(true);// Due to a delayed SelectionKey cancelling deregistering// nature this distribution doesn't work well, it leads to// dead-lock. Let's make sure the service is always processed// by the same thread thus the same Selector.// socketReadThread[incrementAndGet()].addSocketServicePriv(s);//如果IOService是等待读的状态,那个根据 % 算法均衡到不同的线程中去if (s.waitingToRead()) {socketReadThread[s.hashCode() % socketReadThread.length].addSocketServicePriv(s);}//如果是待发送的IOService则根据 % 算法负载到写线程中去if (s.waitingToSend()) {socketWriteThread[s.hashCode() % socketWriteThread.length].addSocketServicePriv(s);}}/*** 核心移除IOService方法* @param s*/public static void removeSocketService(IOService<Object> s) {//设置就绪状态falses.setSocketServiceReady(false);//读写线程中都移除这个IOService对象socketReadThread[s.hashCode() % socketReadThread.length].removeSocketServicePriv(s);socketWriteThread[s.hashCode() % socketWriteThread.length].removeSocketServicePriv(s);}
两个都是静态方法,其核心原理就是用过hash 和取模算法分配IOService到SocketThread数组中的不同SocketThread线程中去。
SocketThread的run方法分析
public void run() {while (!stopping) {try {clientsSel.select();Set<SelectionKey> selected = clientsSel.selectedKeys();int selectedKeys = selected.size();//就绪的Key为0 且 等待的IOService为0if ((selectedKeys == 0) && (waiting.size() == 0)) {//重新创建Selector条件if ((++empty_selections) > MAX_EMPTY_SELECTIONS) {recreateSelector();}} else {empty_selections = 0;if (selectedKeys > 0) {//遍历就绪的Keyfor (SelectionKey sk : selected) {//从就绪的Key中拿到IOService对象IOService s = (IOService) sk.attachment();try {...sk.cancel();//添加到“待完成” 跳表中forCompletion.add(s);} catch (CancelledKeyException e) {//异常就强制停止IOServices.forceStop();}}}clientsSel.selectNow();}//将waiting跳表中的IOService分类注册到当前SocketThread的Selector上addAllWaiting();IOService serv = null;//先是从waiting 跳表注册到到当前forCompletion,然后再从//forCompletion跳表拿到最小的一个不为空,//就丢到completionService中执行,执行完只需要take()就能拿到执行完的对象while ((serv = forCompletion.pollFirst()) != null) {completionService.submit(serv);}} catch (Exception e) {recreateSelector();}}}
SocketThread本身是一个线程,其核心的方法和流程就在run()方法里面,以上代码是我精简之后留下的核心代码,具体的逻辑就是循环将waiting跳表集合中的IOServie注册到Selector上,并监听就绪的IOService,将其添加到forCompletion跳表集合中,然后从forCompletion中挨个取出,提交到completionService线程池中。供线程池调用IOService核心的call()方法进行数据的读写。
小结
tiagse的IO线程处理模型充分利用多线程和单一职责的设计,ConnectionOpenThread负载客户端连接的建立、SocketThread线程组负责监听就绪的IO对象,以及读写IO的分类、缓冲等,CompletionService线程池负责执行IOService的call方法(主要是处理IO的读写操作),以及解耦执行和执行结果的获取操作。ResultsListener线程负责循环利用没有关闭的IOService对象。合理的线程模型设计,更有利于提高系统的效率。
相关文章:
tigase源码学习杂记-IO处理的线程模型
前言 tigase是一个高性能的服务器,其实个人认为作为即时通讯的服务器,高性能主要体现在他对IO复用,和多线程的使用上,今天来学习一下他的IO的线程处理模型的源码,并记录一下他优秀的设计。 概述 tigase是使用的NIO作…...
电商秒杀系统技术栈与难点解析 - Java架构师面试实战
电商秒杀系统技术栈与难点解析 - Java架构师面试实战 第一轮提问 面试官:马架构,欢迎参加我们公司的面试。首先,请您简单介绍一下自己。 马架构:您好,我叫马架构,拥有十年的Java研发经验和架构设计经验&…...
ASP.NET MVC 入门指南三
16. 安全性 16.1 身份验证和授权 身份验证:确认用户的身份。ASP.NET MVC 支持多种身份验证方式,如表单身份验证、Windows 身份验证和 OAuth 等。 表单身份验证:用户通过输入用户名和密码登录,服务器验证后颁发一个身份验证票证&…...
导览项目KD-Tree最近地点搜索优化
背景描述 我在做一个校园导览的小程序的时候,涉及到最近地点搜索的业务功能,根据当前位置搜索最近的校园地点,比如教学楼,图书馆,自习室,办事地点等等。 我最初想到的办法就是获取用户当前位置的经纬度后&…...
【Pandas】pandas DataFrame rmul
Pandas2.2 DataFrame Binary operator functions 方法描述DataFrame.add(other)用于执行 DataFrame 与另一个对象(如 DataFrame、Series 或标量)的逐元素加法操作DataFrame.add(other[, axis, level, fill_value])用于执行 DataFrame 与另一个对象&…...
苹果(IOS)手机怎么开启开发者模式(简单明了版)
苹果手机怎么开启开发者模式(简单明了版) iOS 16 以后,苹果新增了「开发者模式」。如果你要在 iPhone 上运行自己开发的 App,比如通过 Xcode 或其它工具安装测试包,必须先开启这个模式。 下面是开启方法👇…...
Agent2Agent
rag系列文章目录 文章目录 rag系列文章目录前言一、协议设计原则与技术基础二、通信机制与消息格式三、身份验证与安全设计四、能力发现与任务协作总结 前言 谷歌于2025年4月推出了A2A(Agent2Agent)协议,旨在解决当前AI智能体生态中的互操作…...
【MCP】了解远程MCP调用背后使用的SSE协议
本文介绍了远程MCP使用的SSE协议,通过wireshark抓包的方式了解MCP客户端和服务端之间通过SSE协议交互涉及到的请求与响应。 1. 什么是SSE协议? 参考:https://zhuanlan.zhihu.com/p/1894024642395619635和https://blog.csdn.net/aerror/artic…...
Log4j Properties 配置项详细说明
Log4j Properties 配置项详细说明 1. 核心配置项说明 根日志记录器:定义全局日志级别和输出目标 log4j.rootLogger [级别], appender1, appender2,...Appender 定义:指定日志输出目标(控制台、文件等) log4j.appender.[名称].[属…...
哪些物联网框架支持多协议接入?选型指南与核心能力解析
在物联网(IoT)领域,设备通信协议的多样性(如MQTT、CoAP、Modbus、Zigbee等)是开发者面临的核心挑战之一。选择支持多协议接入的物联网框架,可以显著降低异构设备连接的复杂度,提升系统的兼容性和…...
第三方测试机构如何保障软件质量并节省企业成本?
在软件行业,第三方测试机构扮演着极其重要的角色。他们提供独立且专业的测试服务,目的是为了保障软件的质量以及提升用户的使用体验。 专业独立 测试机构拥有经验丰富的测试员和严谨的测试流程。他们会对软件各项功能进行细致检验,力求不放…...
Eigen迭代求解器类
1. 迭代求解器核心类概览 Eigen 提供多种迭代法求解稀疏线性方程组 AxbAxb,适用于大规模稀疏矩阵: 求解器类适用矩阵类型算法关键特性ConjugateGradient对称正定(SPD)共轭梯度法(CG)高精度,内…...
AI 与高性能计算的深度融合:开启科技新纪元
在当今科技迅猛发展的时代,人工智能(AI)与高性能计算(HPC)正以前所未有的态势深度融合,这种融合宛如一场强大的风暴,席卷并重塑着众多领域的格局。从科学研究的突破到商业应用的革新,…...
写入cache时数据格式错误产生的ERRO导致整个测试框架无法运行
背景 在yaml文件里面提取request放入缓存时,request是form-data,错用jsonpath提取并写入缓存,导致后面的所有运行都异常 原因 起因是我想引用请求体的Uid,提取方式用错了,所以可以看到最后一段current_request_set_…...
3:QT联合HALCON编程—海康相机SDK二次程序开发
思路: 1.定义带UI界面的主函数类 1.1在主函数中包含其它所有类头文件,进行声明和实例化;使用相机时,是用公共相机的接口在某一个具体函数中去实例化具体的海康相机对象。 1.2设计界面:连接相机,单次采集&a…...
图论---LCA(倍增法)
预处理 O( n logn ),查询O( log n ) #include<bits/stdc.h> using namespace std; typedef pair<int,int> pii; const int N40010,M2*N;//是无向边,边需要见两边int n,m; vector<int> g[N]; //2的幂次范围 0~15 int depth[N],fa[N][1…...
Bento4的安装和简单转码
1.下载Bento4 2解压复制到安装位置 3配置环境变量 在path下配置 5.视频转码为Dash 视频分片化 mp4fragment --track video --fragment-duration 4000 C:\Users\zcc\Downloads\Video\gg.mp4 C:\Users\zcc\Downloads\Video\out3\input_fragmented.mp4分片化的视频转码为dash…...
用python写一个相机选型的简易程序
最近有点忙,上来写的时间不多。 今天就把之前写的一个选型的简易程序,供大家参考。 代码: import sys from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,QLabel, QLineEdit, QPushButton, QGro…...
论人际关系发展的阶段
朋友关系的建立和发展是一个渐进的过程,通常需要经历情感积累、信任磨合和价值观融合等阶段。以下是朋友关系发展的详细阶段划分及核心特征: 一、表层接触阶段(社交试探期) 核心特征:以信息交换为主,关系停…...
2软考系统架构设计师:第一章系统架构概述 - 练习题附答案及超详细解析
第一章系统架构概述综合知识单选题 每道题均附有答案解析: 1. 系统架构的核心定义是什么? A. 系统代码的实现细节 B. 系统组件、组件关系及与环境交互的高层次设计蓝图 C. 用户界面的设计规范 D. 数据库表结构的详细设计 答案:B 解析&…...
华为OD机试真题——素数之积RSA加密算法(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳实现
2025 A卷 100分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C、GO六种语言的最佳实现方式; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析; 本文收录于专栏:《2025华为OD真题目录…...
k8s中资源的介绍及标准资源namespaces实践
文章目录 第1章 k8s中的资源(resources)介绍1.1 k8s中资源(resouces)的分类1.2 k8s中资源(resources)的级别1.3 k8s中资源(resources)的API规范1.4 k8s中资源(resources)的manifests 第2章 k8s中的标准资源之namespaces的实践2.1 基本介绍2.2 编写相关ns资源对象的manifests2.3…...
k8s学习记录(四):节点亲和性
一、前言 在上一篇文章里,我们了解了 Pod 中的nodeName和nodeSelector这两个属性,通过它们能够指定 Pod 调度到哪个 Node 上。今天,我们将进一步深入探索 Pod 相关知识。这部分内容不仅信息量较大,理解起来也有一定难度࿰…...
联想笔记本电脑在Windows下通过联想驱动实现风扇控制
概述 本文旨在解决部分联想笔记本电脑无法使用主流的风扇控制工具(如Fan Control, SpeedFan)控制风扇的问题。主流的风扇控制工具在这些电脑上会因无法找到控制风扇的EC寄存器而无法发挥作用。但这是不是就意味着没办法控制风扇了呢?答案是否…...
Java单链表题目
Java链表题目练习 移除链表元素反转单链表链表的中间节点返回倒数第K个节点合并两个有序列表判断链表是否回文 学习了知识,就要进行其检验自己是否真正学会,练习题目来加强对知识的理解,今天就来练习一下链表题目 移除链表元素 目的ÿ…...
springboot入门-controller层
在 Spring Boot 中,Controller 层是处理 HTTP 请求的核心组件,负责接收客户端请求、调用业务逻辑(Service 层)并返回响应。其核心原理基于 Spring MVC 框架,通过注解驱动的方式实现请求的路由和参数绑定。以下是 Contr…...
游戏引擎学习第245天:wglChoosePixelFormatARB
Blackboard: PBO(像素缓冲对象) 我们将一起编写一个完整的游戏。老实说,我原本以为我们会花更长时间来实现异步纹理上传,结果我们只用了两天时间,主要原因是我们没有设置标志来真正告诉程序下载纹理,所以这…...
中国大陆DNS服务选择指南:阿里云VS AWS,合规性与最佳实践
导语 在中国大陆开展互联网业务时,DNS服务的选择不仅关乎性能,更涉及合规性问题。本文将深入探讨DNS服务商选择的自由度、阿里云与AWS DNS服务的优劣势,以及如何在确保合规的同时优化您的域名解析策略。无论您是初创公司还是跨国企业,这份指南都将助您在复杂的中国互联网环境中…...
LLaMa Factory大模型微调
LLaMa Factory大模型微调 大模型微调平台&硬件LLaMA-Factory安装hfd下载hugging face模型自我认知微调Alpaca数据集指令监督微调断点续训 大模型微调 微调自我认知微调特定领域数据集。 平台&硬件 Ubuntu20.04显卡:M40 24G 2080TI 22G微调框架ÿ…...
git和github的使用指南
目录 1.git初始化本地仓库 2.远程仓库 3.如何将自己的代码上传到远程仓库的某一个分支 1.git初始化本地仓库 在项目目录中初始化 Git 仓库: cd your-project-directory git init 将文件添加到暂存区: git add . //添加所有文件 git add <fi…...
如何快速轻松地恢复未保存的 Word 文档:简短指南
文字处理器已经存在了几十年,其中许多已经变得非常擅长防止问题。丢失未保存的数据是一个常见问题,因此办公软件通常带有恢复文件的方法。在本文中,我们将介绍如何恢复 Word 文档,即使您尚未保存它。 确保数据安全的最佳方法是保…...
【Linux网络】打造初级网络计算器 - 从协议设计到服务实现
📢博客主页:https://blog.csdn.net/2301_779549673 📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! &…...
基于STM32定时器中断讲解(HAL库)
基于STM32定时器中断讲解(HAL库) 1、定时器简单介绍 以STM32F103C8T6中几个定时器为例: TIM1:这是一个高级定时器,不仅具备基本的定时中断功能,还拥有内外时钟源选择、输入捕获、输出比较、编码器接口以…...
《Vue3学习手记5》
pinia 共享的数据交给集中状态管理 引入与使用 //main.ts // 引入Pinia import {createPinia} from "pinia"const piniacreatePinia() app.use(pinia)案例: <template><div class"count"><h2>当前和为:{{ sum…...
MySQL多查询条件下深度分页性能优化技巧及示例总结
深度分页(Deep Pagination)是MySQL中常见的性能瓶颈问题,特别是在多查询条件下,当offset值很大时,查询性能会急剧下降。本文将总结多种优化技巧,并提供实际示例。 一、深度分页的性能问题分析 当执行类似SELECT * FROM table WHERE condition1 AND condition2 LIMIT 1000…...
3、初识RabbitMQ
界面上的导航栏共分6部分,分别代表不同的意思 一、Producer和Consumer Producer: 生产者, 是RabbitMQ Server的客户端, 向RabbitMQ发送消息 Consumer: 消费者, 也是RabbitMQ Server的客⼾端, 从RabbitMQ接收消息 Broker:其实就是RabbitMQ Server, 主要…...
量子计算与GPU的异构加速:基于CUDA Quantum的混合编程实践
一、量子模拟的算力困境与GPU破局 量子计算模拟面临指数级增长的资源需求:n个量子比特的态向量需要存储2^n个复数。当n>30时,单机内存已无法承载(1TB需求)。传统CPU模拟器(如Qiskit Aer)在n28时计算…...
在Spring Boot项目中实现Word转PDF并预览
在Spring Boot项目中实现Word转PDF并进行前端网页预览,你可以使用Apache POI来读取Word文件,iText或Apache PDFBox来生成PDF文件,然后通过Spring Boot控制器提供文件下载或预览链接。以下是一个示例实现步骤和代码: 1. 添加依赖 …...
Windows怎样使用curl下载文件
安装curl 从官网下载:访问curl官方网站,根据系统位数(32 位或 64 位)选择相应的版本进行下载。下载完成后,双击安装程序并按照提示进行安装。也可以选择自定义安装路径,记住安装路径,后续配置环…...
priority_queue的学习
priority_queue的介绍 优先级队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元素)。优先队列被…...
浅谈Java 内存管理:栈与堆,垃圾回收
在Java编程世界里,内存管理是一项极为关键的技能,它就像程序运行背后的“隐形守护者”,默默影响着程序的性能与稳定性。今天,咱们就来简单学习一下Java内存管理中的两大核心要点:栈与堆的内存分配机制,以及…...
windows下查看idea运行的进程占的JVM情况工具
jconsole 查看JVM 查看线程数 自己测试时,可以先不把线程关闭查效果。 也可以用这工具查下是不是有线程一直在增加。...
【新技术】微软 Azure Test Impact Analyzer (TIA) 全面解析
目录 一、什么是 Azure Test Impact Analyzer?二、核心功能与优势三、如何掌握 Azure TIA?四、工作中的典型应用场景五、最佳实践与注意事项六、总结 一、什么是 Azure Test Impact Analyzer? Azure Test Impact Analyzer (TIA) 是微软 Azur…...
JAVA服务内存缓慢上涨,年轻代GC正常但Full GC频繁,如何定位?
1. 分析 : 年轻代GC正常,说明年轻代的对象回收没有问题,可能大部分对象都是朝生夕死的,所以Minor GC能有效清理。但Full GC频繁,通常意味着老年代空间不足,导致频繁进行Full GC来回收老年代。而内存缓慢上…...
浏览器界面无显示,提示“代理服务器可能有问题”,这是怎么回事呢?
前言 🌟🌟本期讲解浏览器代理服务器解决办法介绍~~~ 🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客 🔥 你的点赞就是小编不断更新的最大动力 🎆那么废话不…...
C#中的弱引用使用
弱引用(Weak Reference)是一种特殊的引用类型,它允许你引用一个对象,但不会阻止该对象被垃圾回收器(GC)回收。弱引用通常用于需要缓存或跟踪对象,但又不希望因保留引用而导致内存泄漏的场景。弱…...
在Linux虚拟机下使用vscode,#include无法跳转问题
总结:需要通过Linux指令来添加编译器和压缩文件,解压,这样获得的编译器会具有可执行权限类似于 -rwxr-xr-x 1 user user 12345 Apr 26 14:22 myscript.sh 如果你直接从window中拖入文件到Linux文件下,你需要自己来再度开启可编译…...
MIL、SIL、HIL与Back-to-Back测试详解:从模型到硬件的完整验证链
1. 引言 在嵌入式系统和控制算法开发中,MIL、SIL、HIL和Back-to-Back测试构成了从模型设计到硬件部署的完整验证流程。它们覆盖不同开发阶段,确保系统功能正确性、实时性和可靠性。 本文将清晰解析这四种测试方法的核心概念、应用场景及差异。 2. 四种测…...
【Android Compose】焦点管理
官方文档链接: https://developer.android.google.cn/develop/ui/compose/touch-input/focus?hlzh-cn 1、更改焦点遍历顺序 1.1、替换一维遍历顺序 (1)创建焦点引用对象: /// 创建4个引用对象(二选一)…...
启动命令汇总(Redis / Kafka / Flume / Spark)
本文总结了本地开发环境(Windows系统)中启动推荐系统所需的所有组件命令,包括 Redis、Kafka、Flume 及 SparkStreaming 程序的启动流程。 1. 启动 Redis 进入 Redis 安装目录,执行: redis-server.exe测试连接&#x…...