当前位置: 首页 > news >正文

【多线程】线程池核心数到底如何配置?

🥰🥰🥰来都来了,不妨点个关注叭!
👉博客主页:欢迎各位大佬!👈

在这里插入图片描述

文章目录

  • 1. 前置回顾
  • 2. 动态线程池
    • 2.1 JMX 的介绍
      • 2.1.1 MBeans 介绍
    • 2.2 使用 JMX + jconsole 实现动态修改线程池
      • 2.2.1 介绍 ManagementFactory
      • 2.2.2 JMX 与 ManagementFactory 的区别与联系

回顾这期内容:【多线程】线程池,介绍了线程池,其中 5.3 介绍如何给线程池设置合适线程数量(这期内容会再回顾一遍),这期内容,具体讨论一下,线程池核心数到底如何配置~

1. 前置回顾

在实际开发中如何给线程池设置合适的线程数量呢?

我们要知道,线程不是越多越好,线程的本质上是要在 CPU 上调度的,一个线程池的线程数量设置为多少合适,这需要结合实际情况实际任务决定,一般分为 CPU 密集型和 IO 密集型,通常是如下配置:

  1. CPU 密集型任务:N+1,主要做一些计算工作,要在 CPU上运行
  2. IO 密集型任务:2N+1,主要是等待 IO 操作,比如等待读写硬盘,读写网卡等,不怎么消耗 CPU 资源
    (其中 N 为 CPU 的核心数量)

Q:为什么要加 1

A:+1 个线程是为了在某个线程因为一些原因,比如缓存未命中、遇到短暂的指令停顿等,暂时阻塞时,能有一个额外的线程可以在 CPU 上运行,从而充分利用 CPU 的空闲时间,避免 CPU 核心出现空闲等待的情况,提高整体的 CPU 利用率,应对一些特殊情况或系统开销等,确保即使在某些线程出现意外阻塞等情况时,系统仍能有额外的线程来维持一定的处理能力,保证系统的稳定性和性能

极端情况下,如果线程全是使用 CPU 运行,线程数就不应该超过 CPU 核心数(逻辑核心,比如一个电脑是6核12线程,即12个逻辑核心,以12为基准),如果线程全是使用的 IO,则线程数可以设置很多,远远超出 CPU 的核心数

在实际开发中,很少有这么极端的情况,就是以实际情况来设定,需要具体通过测试的方式来确定,测试方式的大体思路是,运行程序,通过记录时间戳计算一下执行时间,同时监测资源的使用状态,线程数量取一个执行效率可以并且占用资源也还可以的数量~

这里的两个关键点:

  • 记录时间戳计算执行时间
  • 监测资源的使用状态

计算执行时间的具体操作方法是,可以统计一个完整的请求中,耗费 CPU 计算的过程占用了多少时间,等待的过程,如读取缓存、读取 DB 等占用了多少时间,假设统计结果是 100ms 用来做 CPU 计算,900ms 都是 IO 相关的操作,不占 CPU 时间,那么就可以通过 (100+900) / 100 的计算公式,得出对于单核 CPU,设置线程数为 10 就可以把 CPU 跑满,同理,如果是 6 核 CPU,那么就设置线程数为 60

监测资源的使用状态具体操作方法,在程序执行过程中,持续监测 CPU、内存、线程等资源的使用情况

具体代码如下:

import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.ThreadMXBean;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ResourceMonitoringExample {// 这里进行模拟任务static class Task implements Runnable {@Overridepublic void run() {try {// 模拟耗时操作Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {int threadCount = 10; // 初始线程数量ExecutorService executor = Executors.newFixedThreadPool(threadCount);// 记录开始时间long startTime = System.currentTimeMillis();// 提交任务for (int i = 0; i < 20; i++) {executor.submit(new Task());}// 关闭线程池executor.shutdown();while (!executor.isTerminated()) {// 监测资源使用状态monitorResources();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}// 记录结束时间long endTime = System.currentTimeMillis();long executionTime = endTime - startTime;System.out.printf("程序执行时间: %d 毫秒%n", executionTime);}// 监测资源使用状态private static void monitorResources() {// 监测 CPU 使用情况OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();if (osBean instanceof com.sun.management.OperatingSystemMXBean) {com.sun.management.OperatingSystemMXBean sunOsBean = (com.sun.management.OperatingSystemMXBean) osBean;double cpuLoad = sunOsBean.getSystemCpuLoad();if (cpuLoad >= 0) {System.out.printf("当前系统 CPU 使用率: %.2f%%%n", cpuLoad * 100);}}// 监测线程数量ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();int threadCount = threadBean.getThreadCount();System.out.printf("当前活动线程数量: %d%n", threadCount);}
}

其中:ManagementFactory 是 Java 中的一个实用工具类,位于 java.lang.management 包下,该类提供了一系列静态方法,用于获取 JVM 的各种管理接口实例,这些管理接口允许你监控和管理 JVM 的运行时状态、系统资源使用情况等(后文会详细介绍)~

总结:

线程池的核心参数并不是这么冰冷冷且固定的数字,还是需要结合实际场景考虑,一般线程池核心数,可以根据实际情况进行计算后配置~

下面介绍动态线程池,我们一起来看看~

2. 动态线程池

线程池线程数的设置是个难题,线程池核心数到底如何配置?最好的办法是能够动态调整线程池线程数,并能够看到调整后的效果,也就是线程利用率,有一个工具能够实现这样的效果 —— 使用 JMX

那么 JMX 是什么呢? 我们先来一起了解一下!

2.1 JMX 的介绍

  1. JMX 是什么:JMX(Java Management Extensions)是 Java 平台的一部分,它提供了一种管理和监控 Java 应用程序的标准方法,即是一个为应用程序、设备、系统等植入管理功能的框架,JMX 允许监控和管理系统资源、应用程序和服务,以及获取关于这些实体的运行时信息,简单来说,就是通过 JMX 可以动态查看对象的运行信息,并且可以动态修改对象属性~
  2. JMX 的架构:如下图
    在这里插入图片描述

分析这张图我们可以发现,JMX 底层是由很多不同的 MBeans 组成的,即 MBeans 是 JMX 的核心

2.1.1 MBeans 介绍

MBeans 是什么:它们是实现了特定接口的 Java 对象,用于表示可以被监控和管理的资源

MBeans 的类型:可以分为四种不同的类型

  • Standard MBeans
  • Dynamic MBeans
  • Open MBeans
  • Model MBeans

MBeans 的作用:这些 MBeans 的作用就是获取对象的信息,或是修改对象信息,都是通过 MBeans 来完成的

MBeans 的用法所有的 MBeans 都需要注册到 MBeanServer 上,然后再通过一些外部工具如 JMX、Web 浏览器等,就可以去获取或者修改 MBeans 的信息了

补充:
Q:那 MBean Server 是什么呢?
A:这里的 MBean Server 是一个代理,它提供一个注册、检索和操作 MBeans 的 API,它是 JMX 架构中的核心组件,负责管理所有 MBeans 的生命周期

接下来,我们一起来看看如何使用 JMX 诗仙女动态修改线程池

2.2 使用 JMX + jconsole 实现动态修改线程池

1)自定义一个动态线程池

首先,我们先来自定义一个动态线程池,如下:

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;/*** Created with IntelliJ IDEA.* Description:* User: 26727* Date: 2025-02-05* Time: 18:41*/
public class DynamicThreadPool {private ThreadPoolExecutor threadPoolExecutor;public DynamicThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);}public ThreadPoolExecutor getThreadPoolExecutor() {return threadPoolExecutor;}public void setCorePoolSize(int corePoolSize) {threadPoolExecutor.setCorePoolSize(corePoolSize);}public void setMaximumPoolSize(int maximumPoolSize) {threadPoolExecutor.setMaximumPoolSize(maximumPoolSize);}
}

动态线程池的相关参数如下,动态线程池其实就是传统的线程传统的线程池对象 ThreadPoolExecutor 封装了一下,并且提供了两个方法 setCorePoolSize 和 setMaximumPoolSize,这样通过这两个方法,我们就可以动态设置线程池的线程数了~

在这里插入图片描述

2)自定义一个 MBean 接口

接下来,我们自定义一个 MBean 这个接口中提供四个方法,分别用来获取或者设置线程数的信息

public interface DynamicThreadPoolMXBean {int getCorePoolSize();void setCorePoolSize(int corePoolSize);int getMaximumPoolSize();void setMaximumPoolSize(int maximumPoolSize);
}

3)自定义类实现 DynamicThreadPoolMXBean 接口

接着,我们自定义类实现 DynamicThreadPoolMXBean 接口,并继承 StandardMBean 类,如下:

import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.StandardMBean;
import java.lang.management.ManagementFactory;/*** Created with IntelliJ IDEA.* Description:* User: 26727* Date: 2025-02-04* Time: 23:02*/
public class DynamicThreadPoolMBean extends StandardMBean implements DynamicThreadPoolMXBean {private DynamicThreadPool dynamicThreadPool;public DynamicThreadPoolMBean(DynamicThreadPool dynamicThreadPool) throws Exception {super(DynamicThreadPoolMXBean.class);this.dynamicThreadPool = dynamicThreadPool;registerMBean();}private void registerMBean() {try {MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();ObjectName name = new ObjectName("org.javaboy:type=DynamicThreadPool");mbs.registerMBean(this, name);} catch (Exception e) {e.printStackTrace();}}@Overridepublic int getCorePoolSize() {return dynamicThreadPool.getThreadPoolExecutor().getCorePoolSize();}@Overridepublic void setCorePoolSize(int corePoolSize) {dynamicThreadPool.setCorePoolSize(corePoolSize);}@Overridepublic int getMaximumPoolSize() {return dynamicThreadPool.getThreadPoolExecutor().getMaximumPoolSize();}@Overridepublic void setMaximumPoolSize(int maximumPoolSize) {dynamicThreadPool.setMaximumPoolSize(maximumPoolSize);}
}

【解析】

  • 构造函数接受一个 DynamicThreadPool 类型的参数,用于初始化 dynamicThreadPool 的成员变量
    super(DynamicThreadPoolMXBean.class) 调用父类 StandardMBean 的构造函数,传入 DynamicThreadPoolMXBean 类的 Class 对象,用于指定 MBean 的管理接口,调用 registerMBean() 方法将该 MBean 注册到 JMX 平台 MBean 服务器中,即在构造器中,调用了 registerMBean() 方法,这个方法用来将当前对象注册到 MBeanServer 上~

  • 注册 MBean 方法 registerMBean()ManagementFactory.getPlatformMBeanServer() 获取平台 MBean 服务器的实例,ObjectName 用于唯一标识 MBean,这里使用 org.javaboy:type=DynamicThreadPool 作为 MBean 的名称,
    mbs.registerMBean(this, name) 将当前 DynamicThreadPoolMBean 实例注册到 MBean 服务器中

4)执行代码

最后,就可以启动自己的这段代码了~

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;/*** Created with IntelliJ IDEA.* Description:* User: 26727* Date: 2025-02-04* Time: 23:07*/
public class Main {public static void main(String[] args) throws Exception {DynamicThreadPool dynamicThreadPool = new DynamicThreadPool(2, 6, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10));DynamicThreadPoolMBean mBean = new DynamicThreadPoolMBean(dynamicThreadPool);while (true) {System.out.println("CorePoolSize:"+dynamicThreadPool.getThreadPoolExecutor().getCorePoolSize());System.out.println("MaximumPoolSize:"+dynamicThreadPool.getThreadPoolExecutor().getMaximumPoolSize());try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}}}
}

为了看到线程池的线程数量,这里使用了一个死循环一直打印线程数量信息,这样一会通过 jconsole 修改线程池信息的时候,就能看到修改的效果了~

程序启动之后,使用 jconsole 连接上当前应用程序,如下图:

(jconsole 使用忘记的小伙伴可回顾往期内容:【多线程】如何使用jconsole工具查看Java线程的详细信息?)

点击 Main 进入连接

在这里插入图片描述
点击 MBean 这个选项卡位置,可以看到刚刚配置的 MBean,右侧的值则可以点击直接修改,修改之后,回到应用程序控制台,可以发现线程相关数据已经发生变化了,实现了动态修改的效果~

在这里插入图片描述
可以看到,控制台信息已经发生变化,如下:

在这里插入图片描述
这样就可以动态修改了!

2.2.1 介绍 ManagementFactory

可以看到上面使用了 ManagementFactory 类,下面具体介绍其用法:

1) 获取线程管理接口实例 —— getThreadMXBean()

返回一个 ThreadMXBean 实例,用于监控和管理 Java 虚拟机中的线程,通过该接口,可以获取线程的各种信息,如线程的状态、CPU 时间、阻塞时间等

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;public class ThreadMonitoringExample {public static void main(String[] args) {// 获取 ThreadMXBean 实例ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();// 获取所有线程的 IDlong[] threadIds = threadMXBean.getAllThreadIds();for (long threadId : threadIds) {// 获取线程信息System.out.println("Thread ID: " + threadId + ", Thread Name: " + threadMXBean.getThreadInfo(threadId).getThreadName());}}
}

2)获取内存管理接口实例 —— getMemoryMXBean()

返回一个 MemoryMXBean 实例,用于监控和管理 Java 虚拟机的内存使用情况。通过该接口,可以获取堆内存和非堆内存的使用情况,还可以触发垃圾回收操作~

import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;public class MemoryMonitoringExample {public static void main(String[] args) {// 获取 MemoryMXBean 实例MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();// 获取堆内存使用情况MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();System.out.println("Heap Memory Usage: " + heapMemoryUsage);// 获取非堆内存使用情况MemoryUsage nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();System.out.println("Non-Heap Memory Usage: " + nonHeapMemoryUsage);}
}

3)获取运行时管理接口实例 —— getRuntimeMXBean()

返回一个 RuntimeMXBean 实例,用于获取 Java 虚拟机的运行时信息,如 JVM 的启动时间、系统属性、命令行参数等

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;public class RuntimeInfoExample {public static void main(String[] args) {// 获取 RuntimeMXBean 实例RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();// 获取 JVM 启动时间long startTime = runtimeMXBean.getStartTime();System.out.println("JVM Start Time: " + startTime);// 获取系统属性System.out.println("System Properties: " + runtimeMXBean.getSystemProperties());}
}

ManagementFactory 类为 Java 开发者提供了便捷的方式来监控和管理 JVM 的运行时状态,通过获取不同的管理接口实例,可以深入了解 JVM 的内部运行情况,从而进行性能调优、故障排查等相关工作~

2.2.2 JMX 与 ManagementFactory 的区别与联系

区别:

JMX —— Java 扩展管理,是一个为应用程序、设备、系统等植入管理功能的框架

ManagementFactory —— Java 标准库中用于辅助使用 JMX 功能的实用工具

联系:

  • ManagementFactory 是 JMX 功能使用的便捷入口
    JMX 架构复杂:JMX 定义了一套完整的架构,包括 MBean、MBeanServer等核心组件,使用 JMX 进行管理和监控时,需要涉及多个步骤和类的使用,整体较为复杂,而 ManagementFactory 简化操作,ManagementFactory 类提供了一系列静态方法,通过调用这些方法可以方便地获取各种 JMX 管理接口的实例。如,ManagementFactory.getThreadMXBean() 方法返回的 ThreadMXBean 是一个 JMX 的 MXBean,它允许开发者监控和管理 Java 虚拟机中的线程。这些方法隐藏了底层 JMX 架构的复杂性,使得开发者可以更轻松地使用 JMX 功能~
  • ManagementFactory 实例基于 JMX 标准
    ManagementFactory 所返回的各种管理接口实例(如 MemoryMXBean、RuntimeMXBean 等)都是遵循 JMX 规范的 MXBean,这些 MXBean 定义了一组标准的管理操作和属性,可以通过 JMX 代理进行访问和管理,并且可集成到 JMX 系统,通过 ManagementFactory 获取的管理接口实例可以无缝集成到 JMX 系统中。开发者可以将这些 MXBean 注册到 MBeanServer 上,然后使用 JMX 客户端远程或本地监控和管理 Java 应用程序~
  • ManagementFactory 服务于 JMX 监控和管理目的
    支持监控:JMX 的主要目的之一是对 Java 应用程序进行监控和管理,ManagementFactory 所提供的各种管理接口实例可以提供丰富的监控数据,例如,MemoryMXBean 可以提供 Java 虚拟机的内存使用情况,包括堆内存和非堆内存的使用量、峰值等信息;并且ThreadMXBean 可以提供线程的状态、CPU 时间等信息。
    支持管理:除了监控数据,ManagementFactory 所提供的管理接口实例还支持一些管理操作,例如,MemoryMXBean 可以触发垃圾回收操作,ThreadMXBean 可以获取线程的堆栈跟踪信息等,这些操作可以帮助开发者对 Java 应用程序进行动态管理和故障排查~

在这里插入图片描述

💛💛💛本期内容回顾💛💛💛

在这里插入图片描述

✨✨✨本期内容到此结束啦~

相关文章:

【多线程】线程池核心数到底如何配置?

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. 前置回顾2. 动态线程池2.1 JMX 的介绍2.1.1 MBeans 介绍 2.2 使用 JMX jconsole 实现动态修改线程池2.2.…...

Linux find 命令 | grep 命令 | 查找 / 列出文件或目录路径 | 示例

注&#xff1a;本文为 “Linux find 命令 | grep 命令使用” 相关文章合辑。 未整理去重。 如何在 Linux 中查找文件 作者&#xff1a; Lewis Cowles 译者&#xff1a; LCTT geekpi | 2018-04-28 07:09 使用简单的命令在 Linux 下基于类型、内容等快速查找文件。 如果你是 W…...

爬楼梯(dp)杭电复试

一个楼梯共有 nn 级台阶&#xff0c;每次可以走一级或者两级或者三级&#xff0c;问从第 00 级台阶走到第 nn 级台阶一共有多少种方案。 输入格式 一个整数 NN。 输出格式 一个整数&#xff0c;表示方案总数。 数据范围 1≤N≤201≤N≤20 输入样例&#xff1a; 4输出样…...

JVM执行引擎

一、执行引擎的概述: 执行引擎是]ava虚拟机核心的组成部分之一; “虚拟机”是一个相对于“物理机”的概念&#xff0c;这两种机器都有代码执行能力&#xff0c;其区别是物理机的执行引擎是直接建立在处理器、缓存、指令集和操作系统层面上的&#xff0c;而虚拟机的执行引擎则…...

企业四要素如何用PHP进行调用

一、什么是企业四要素&#xff1f; 企业四要素接口是在企业三要素&#xff08;企业名称、统一社会信用代码、法定代表人姓名&#xff09;的基础上&#xff0c;增加了一个关键要素&#xff0c;通常是企业注册号或企业银行账户信息。这种接口主要用于更全面的企业信息验证&#x…...

基于springboot河南省旅游管理系统

基于Spring Boot的河南省旅游管理系统是一种专为河南省旅游行业设计的信息管理系统&#xff0c;旨在整合和管理河南省的旅游资源信息&#xff0c;为游客提供准确、全面的旅游攻略和服务。以下是对该系统的详细介绍&#xff1a; 一、系统背景与意义 河南省作为中国的中部省份&…...

arm 下 多线程访问同一变量 ,使用原子操作 性能差问题

arm下原子操作性能差的原因 Linux Kernel(armv8-aarch64) 的原子操作的底层实现 - 极术社区 - 连接开发者与智能计算生态 arm 下如何解决 ARMs LSE (for atomics) and MySQL – MySQL On ARM – All you need to know about MySQL (and its variants) on ARM. arm 下lse 和…...

嵌入式工程师必学(143):模拟信号链基础

概述: 我们每天使用的许多电子设备,以及我们赖以生存的电子设备,如果不使用电子工程师设计的实际输入信号,就无法运行。 模拟信号链由四个主要元件组成:传感器、放大器、滤波器和模数转换器 (ADC)。这些传感器用于检测、调节模拟信号并将其转换为适合由微控制器或其他数…...

PyQt6/PySide6 的 QDialog 类

QDialog 是 PyQt6 或 PySide6 库中用于创建对话框的类。对话框是一种特殊的窗口&#xff0c;通常用于与用户进行短期交互&#xff0c;如输入信息、显示消息或选择选项等。QDialog 提供了丰富的功能和灵活性&#xff0c;使得开发者可以轻松地创建各种类型的对话框。下面我将详细…...

【AI日记】25.02.05 自由不是一种工具

【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】【读书与思考】 AI kaggle 比赛&#xff1a;Backpack Prediction Challenge感想&#xff1a;这次比赛的数据集的一大特点是信号过弱或者噪声过大&#xff0c;也是一大难点&#xff0c;即使kaggle 官方增加了一…...

【原子工具】快速幂 快速乘

题幂算.一切即1 阴阳迭变积微著&#xff0c;叠浪层峦瞬息功 莫道浮生千万事&#xff0c;元知万象一归宗 文章目录 快速幂原始快速幂&#xff08;O(logn)&#xff09;二分递归形式非递归形式 模下意义的快速幂&#xff08;O(logn)&#xff09;二分递归形式非递归形式 快速乘龟速…...

2024年12月 Scratch 图形化(四级)真题解析 中国电子学会全国青少年软件编程等级考试

202412 Scratch 图形化&#xff08;四级&#xff09;真题解析 中国电子学会全国青少年软件编程等级考试 一、选择题(共10题&#xff0c;共30分) 第 1 题 列表存放全班同学的身高&#xff0c;小猫运行下列程序&#xff0c;下列选项说法正确的是&#xff1f;&#xff08; &#…...

【面试宝典】机器学习:深度解析高频面试题与解答策略

目录 &#x1f354; 机器学习中特征的理解 &#x1f354; 机器学习三要素如何理解? &#x1f354; 机器学习中&#xff0c;有哪些特征选择的⼯程⽅法&#xff1f; &#x1f354; 机器学习中的正负样本 &#x1f354; 线性分类器与⾮线性分类器的区别及优劣 &#x1f354…...

使用 ElementUI 和 Spring 实现稳定可靠的文件上传和下载功能

前端(ElementUI) 1. 文件上传 使用 el-upload 组件配置上传接口处理上传成功和失败<template><div><el-uploadclass="upload-demo"action="http://your-server-url/upload":on-success="handleSuccess":on-error="handle…...

Linux驱动---字符设备

目录 一、基础简介 1.1、Linux设备驱动分类 1.2、字符设备驱动概念 二、驱动基本构成 2.1、驱动模块的加载和卸载 2.2、添加LICENNSE以及其他信息 三、字符设备驱动开发步骤 3.1、分配主次设备号 3.1.1 主次设备号 3.1.2静态注册设备号 3.1.3动态注册设备号 3.1.4释…...

FastReport.NET控件篇之交叉表控件

认识交叉表 上面是交叉表的原型&#xff0c;关键的三个单元格。 单元格①&#xff1a;用于扩展行数据&#xff0c;譬如打印学生成绩表时&#xff0c;每个学生一行&#xff0c;那么这个地方就是以学生姓名列进行打印。 单元格②&#xff1a;用于扩展列数据&#xff0c;譬如打印…...

构建高效复杂系统的关键:架构与模块详解

目录 一、复杂系统组成 二、接入系统 (Access System) 三、应用系统 (Application System) 四、基础平台 (Foundation Platform) 五、中间件 (Abundant External Middleware) 六、支撑系统 (Supporting System) 七、总结 参考文章 干货分享&#xff0c;感谢您的阅读&am…...

C++之递归

递归 递归函数是指一个函数直接或间接地调用自身。递归函数通常用于解决可以分解为相似子问题的问题&#xff0c;例如计算阶乘、斐波那契数列、遍历树结构等 基本结构 一个递归函数通常包含两个部分&#xff1a; 基准条件&#xff08;Base Case&#xff09;&#xff1a;这是…...

pushgateway指标聚合问题

一 问题现象 一个job有多个实例推送指标&#xff0c;但是从pushgateway上看这个job的instance字段&#xff0c;只显示一个实例的ip&#xff0c;而不是多个实例。导致在grafana上无法正常根据ip查看监控。 应用的prometheus的配置 management:metrics:tags:application: ${spr…...

mini-lsm通关笔记Week2Day7

项目地址&#xff1a;https://github.com/skyzh/mini-lsm 个人实现地址&#xff1a;https://gitee.com/cnyuyang/mini-lsm 在上一章中&#xff0c;您已经构建了一个完整的基于LSM的存储引擎。在本周末&#xff0c;我们将实现存储引擎的一些简单但重要的优化。欢迎来到Mini-LSM的…...

[权限提升] Windows 提权 维持 — 系统错误配置提权 - 注册表权限配置错误提权

关注这个专栏的其他相关笔记&#xff1a;[内网安全] 内网渗透 - 学习手册-CSDN博客 0x01&#xff1a;注册表权限配置错误提权原理 通常 Windows 中的服务都是以 System 权限运行的&#xff0c;而 Windows 的服务程序的启动路径又是存放在注册表中的&#xff0c;若注册表配置不…...

产品经理的人工智能课 02 - 自然语言处理

产品经理的人工智能课 02 - 自然语言处理 1 自然语言处理是什么2 一个 NLP 算法的例子——n-gram 模型3 预处理与重要概念3.1 分词 Token3.2 词向量化表示与 Word2Vec 4 与大语言模型的交互过程参考链接 大语言模型&#xff08;Large Language Models, LLMs&#xff09;是自然语…...

软件工程导论三级项目报告--《软件工程》课程网站

《软件工程》课程网站 摘要 本文详细介绍了《软件工程》课程网站的设计与实现方案&#xff0c;包括可行性分析、需求分析、总体设计、详细设计、测试用例。首先&#xff0c;通过可行性分析从各方面确认了该工程的可实现性&#xff0c;接着需求分析明确了系统的目标用户群和功能…...

FPGA|IP核PLL调用测试:调用IP核

1、选择tools-》Megawizard plug-In manager 2、选择第一项&#xff0c;下一步 3、选择ATPLL&#xff0c;芯片系列、和输出文件类型&#xff0c;输出文件名称&#xff0c;单击next 4、出现配置PLL界面 5、选择输入时钟频率&#xff0c;单击next 6、生成reset、和locked信号&…...

leetcode_双指针 160.相交链表

160.相交链表 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 思路: 本题中&#xff0c;交点不是数值相等&#xff0c;而是指针相等 双指针遍历两遍后必定相遇&#xff0c…...

TongSearch3.0.4.0安装和使用指引(by lqw)

文章目录 安装准备手册说明支持的数据类型安装控制台安装单节点(如需集群请跳过这一节)解压和启动开启X-Pack Security和生成p12证书&#xff08;之后配置内置密码和ssl要用到&#xff09;配置内置用户密码配置ssl&#xff08;先配置内置用户密码再配ssl&#xff09;配置控制台…...

2021.3.1的android studio版本就很好用

使用最新版的studio有个问题就是gradle版本也比较高&#xff0c;这样就容易出现之前项目不兼容问题&#xff0c;配置gradle可能会出现很多问题比较烦&#xff0c;所以干脆就用老版本的studio...

提示词实践总结

目录 一、要求创建SqlServer表&#xff08;ChatGpt&#xff09; 二、要求生成多层架构代码&#xff08;Cursor&#xff09; 三、要求修改方法返回值类型&#xff08;Cursor&#xff09; 四、要求修改方法入参&#xff08;Cursor&#xff09; 五、复杂的多表关联生成&#…...

【Elasticsearch】Filters聚合

Filters聚合的基本语法 Filters聚合是一种多桶聚合&#xff0c;用于将文档分组到多个桶中&#xff0c;每个桶对应一个过滤条件。以下是Filters聚合的基本语法和结构&#xff1a; 1.基本结构 json { "aggs": { "<aggregation_name>": { "filter…...

Java基础面试题50题

1&#xff0c;""空字符串的作用 package com.neuedu.nineteen;public class Test {public static void main(String[] args) {String s"";for (char i a; i < d; i) {ssi;//输出abc // sis;//输出cba}System.out.println(s);} }如题所示&…...

Django框架的全面指南:从入门到高级

Django框架的全面指南&#xff1a;从入门到高级 目录 引言Django简介安装与配置创建第一个Django项目Django的MVT架构模型&#xff08;Model&#xff09;视图&#xff08;View&#xff09;模板&#xff08;Template&#xff09;URL路由表单处理用户认证与权限Django Admin高级…...

c++继承

继承的概念和定义 继承的概念 继承 (inheritance) 机制是面向对象程序设计 使代码可以复用 的最重要的手段&#xff0c;它允许程序员在 保 持原有类特性的基础上进行扩展 &#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称派生类。继承 呈现了面向对象 程序设计的…...

【Linux系统】分页式存储管理

分页式存储管理 1、虚拟地址和页表的由来 思考一下&#xff0c;如果在没有虚拟内存和分页机制的情况下&#xff0c;每一个用户程序在物理内存上所对应的空间必须是连续的&#xff0c;如下图&#xff1a; 因为每一个程序的代码、数据长度都是不一样的&#xff0c;按照这样的映射…...

cmd执行mysql命令

安装mysql之后如果想使用cmd执行mysql命令&#xff0c;需要怎么操作呢&#xff0c;下面一起看一下。 安装mysql之后&#xff0c;如果直接去cmd窗口执行MySQL命令&#xff0c;窗口可能会提示mysql不是可执行命令。 需要配置系统的环境变量&#xff0c;将mysql的安装路径配置系…...

第一天:Linux内核架构、文件系统和进程管理

目录 Linux核心概念学习笔记一、Linux内核架构(一)内核的任务(二)实现策略(三)内核的组成部分(四)内核源文件目录结构二、Linux文件系统(一)文件系统架构(二)虚拟文件系统的数据结构三、Linux进程管理(一)进程相关概念(二)进程的层次结构(三)新进程创建机制(…...

QT:信号和槽

目录 1.概念 2.信号和槽的使用 2.1代码的方式使用 2.1.1.使用connect关联 2.2图形化界面的方式使用 2.2.1使用流程 2.2.2使用名字关联槽函数 3.自定义信号和槽函数 3.1自定义槽函数 3.2自定义信号 4.总结 1.概念 信号和槽是QT特有的一种机制&#xff0c;信号和槽都是…...

【Linux系统】线程:认识线程、线程与进程统一理解

一、更新认知 之前的认知 进程&#xff1a;一个执行起来的程序。进程 内核数据结构 代码和数据线程&#xff1a;执行流&#xff0c;执行粒度比进程要更细。是进程内部的一个执行分值 更新认识&#xff1a; a. 进程是承担分配系统资源的基本实体b. 线程是OS调度的基本单位 …...

蓝桥杯字串简写(二分)

输入 4 abababdb a b 输出 6 思路&#xff1a; 如果暴力&#xff0c;o(n**2)&#xff0c;超时&#xff0c;想到可以先与处理一下&#xff0c;记录c1出现的位置&#xff0c;再根据c2的位置用二分法看前面有多少个符合条件的c1。 why二分&#xff1a; 代码&#xff1a;一些…...

【C语言】指针详细解读3

1. 数组名的理解 我们使用指针一般访问数组内容时&#xff0c;我们可能会这样写&#xff1a; int arr[10] {1,2,3,4,5,6,7,8,9,10}; int *p &arr[0]; 这⾥我们使⽤ &arr[0] 的⽅式拿到了数组第⼀个元素的地址&#xff0c;但是其实数组名本来就是地址&#xff0c;⽽…...

Python爬虫-如何正确解决起点中文网的无限debugger

前言 本文是该专栏的第45篇,后面会持续分享python爬虫干货知识,记得关注。 本文以起点中文网为例子,针对起点中文网使用控制台调试出现无限debugger的情况,要如何解决? 针对该问题,笔者在正文将介绍详细而又轻松的解决方法。废话不多说,下面跟着笔者直接往下看正文详细…...

畅游Diffusion数字人(15):详细解读字节跳动最新论文——音频+姿态控制人类视频生成OmniHuman-1

Diffusion models代码解读:入门与实战 前言:昨晚字节跳动刚发布了一篇音频+姿态控制人类视频生成OmniHuman-1的论文,效果非常炸裂,并且是基于最新的MM-DiT架构,今天博主详细解读一下这一技术。 目录 贡献概述 方法详解 音频条件注入 Pose条件注入 参考图片条件注入 …...

Windows图形界面(GUI)-QT-C/C++ - QT Dock Widget

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 目录 一、概述 二、使用场景 1. 工具栏 2. 侧边栏 3. 调试窗口 三、常见样式 1. 停靠位置 2. 浮动窗口 3. 可关闭 4. 可移动 四、属性设置 1. 设置内容 2. 获取内容 3. 设置标题 …...

MIT AppInventor v2.74更新的内容

MIT v2.74更新的内容如下&#xff1a; 新的 UI 选择器提示 向菜单、调色板和设计视图添加键盘导航 更新至 Google Blockly 版本 10 按住 Shift 并拖动以选择多个块 当值被拖近并且没有空闲插槽时&#xff0c;文本等块会自动合并并展开列表 将块拖到边缘时工作区会自动滚动 新的…...

使用 Ollama 在 Windows 环境部署 DeepSeek 大模型实战指南

文章目录 前言Ollama核心特性 实战步骤安装 Ollama验证安装结果部署 DeepSeek 模型拉取模型启动模型 交互体验命令行对话调用 REST API 总结个人简介 前言 近年来&#xff0c;大语言模型&#xff08;LLM&#xff09;的应用逐渐成为技术热点&#xff0c;而 DeepSeek 作为国产开…...

Hackmyvm whitedoor

简介 难度&#xff1a;简单 靶机地址&#xff1a; 环境 kali&#xff1a;192.168.194.9 靶机&#xff1a;192.168.194.24 扫描 nmap -sT -sV -A -T4 192.168.194.24 -p- -Pn 三个服务&#xff0c;ftp匿名登录、ssh连接以及web服务 ftp里面只有一个没用的README文件 访问…...

02/06 软件设计模式

目录 一.创建型模式 抽象工厂 Abstract Factory 构建器 Builder 工厂方法 Factory Method 原型 Prototype 单例模式 Singleton 二.结构型模式 适配器模式 Adapter 桥接模式 Bridge 组合模式 Composite 装饰者模式 Decorator 外观模式 Facade 享元模式 Flyw…...

Java的Integer缓存池

Java的Integer缓冲池&#xff1f; Integer 缓存池主要为了提升性能和节省内存。根据实践发现大部分的数据操作都集中在值比较小的范围&#xff0c;因此缓存这些对象可以减少内存分配和垃圾回收的负担&#xff0c;提升性能。 在-128到 127范围内的 Integer 对象会被缓存和复用…...

[特殊字符] ChatGPT-4与4o大比拼

&#x1f50d; ChatGPT-4与ChatGPT-4o之间有何不同&#xff1f;让我们一探究竟&#xff01; &#x1f680; 性能与速度方面&#xff0c;GPT-4-turbo以其优化设计&#xff0c;提供了更快的响应速度和处理性能&#xff0c;非常适合需要即时反馈的应用场景。相比之下&#xff0c;G…...

2024年12月 Scratch 图形化(二级)真题解析 中国电子学会全国青少年软件编程等级考试

202412 Scratch 图形化&#xff08;二级&#xff09;真题解析 中国电子学会全国青少年软件编程等级考试 一、单选题(共25题&#xff0c;共50分) 第 1 题 小猫初始位置和方向如下图所示&#xff0c;下面哪个选项能让小猫吃到老鼠&#xff1f;&#xff08; &#xff09; A. B. …...

【2025】camunda API接口介绍以及REST接口使用(3)

前言 在前面的两篇文章我们介绍了Camunda的web端和camunda-modeler的使用。这篇文章主要介绍camunda结合springboot进行使用&#xff0c;以及相关api介绍。 该专栏主要为介绍camunda的学习和使用 &#x1f345;【2024】Camunda常用功能基本详细介绍和使用-下&#xff08;1&…...