Qt多线程学习初级指南
一、引言部分
1. 多线程编程的重要性
在当今计算环境中,多线程编程已成为开发高性能应用程序的关键技术。现代应用程序面临着三大挑战:
-
GUI响应性:用户界面需要保持流畅响应,即使在进行后台计算时
-
多核利用率:随着多核CPU的普及,单线程程序无法充分利用硬件资源
-
实时处理:音视频处理、实时数据采集等场景需要并发处理能力
QT作为跨平台应用框架,在Linux系统下提供了完善的多线程支持。典型的应用场景包括:
-
后台文件处理(如大型日志分析)
-
网络通信(同时维护多个连接)
-
数据采集与处理(工业控制领域)
-
图形渲染(分离UI线程与渲染线程)
2. QT多线程的优势
QT的多线程实现具有以下独特优势:
信号槽机制:
// 自动跨线程的信号槽连接
connect(workerThread, &WorkerThread::resultReady,mainWindow, &MainWindow::handleResult, Qt::AutoConnection);
内存管理:
-
基于QObject的父子关系自动管理线程生命周期
-
线程退出时自动清理子对象
平台抽象:
-
统一接口适用于Linux/Windows/macOS等平台
-
底层自动选择最佳实现(如Linux下使用pthread)
二、QT多线程基础
1. 核心类解析
QThread关键API:
// 基本使用
QThread *thread = new QThread;
thread->start(); // 开始执行
thread->wait(); // 等待结束// 重要信号
void started(); // 线程启动时发射
void finished(); // 线程结束时发射
同步工具对比:
类名 | 适用场景 | 示例 |
---|---|---|
QMutex | 保护简单临界区 | 计数器访问保护 |
QReadWriteLock | 读多写少场景 | 配置数据访问 |
QSemaphore | 资源池管理 | 数据库连接池 |
QWaitCondition | 线程间条件等待 | 生产者-消费者模型 |
2. 实现方式对比
继承QThread方式:
class MyThread : public QThread {
protected:void run() override {// 线程执行逻辑}
};
MoveToThread方式:
QThread *thread = new QThread;
Worker *worker = new Worker;
worker->moveToThread(thread);
connect(thread, &QThread::started, worker, &Worker::doWork);
选择标准:
-
需要控制运行流程 → 继承QThread
-
事件驱动型任务 → MoveToThread
-
短时并发任务 → QThreadPool
三、实战案例解析
三线程demo
1.运行结果
2.类关系图
3.关系实现细节
线程安全停止:
void WorkerThread::requestStop() {QMutexLocker locker(&m_mutex); // RAII风格锁m_stopRequested = true;
}void WorkerThread::run() {while(true) {{QMutexLocker locker(&m_mutex);if(m_stopRequested) break;}// 工作逻辑...}
}
跨线程UI更新
// WorkerThread中
emit statusUpdated("Processing item " + QString::number(i));// MainWindow中
connect(thread, &WorkerThread::statusUpdated,this, [this, threadId](const QString &msg){m_labels[threadId]->setText(msg); // 自动排队到UI线程执行
});
4.详细代码
workerthread.h
#ifndef WORKERTHREAD_H
#define WORKERTHREAD_H#include <QThread>
#include <QString>
#include <QMutex>/*** @brief 工作线程类,继承自QThread** 演示QT5中创建自定义线程类的标准方式*/
class WorkerThread : public QThread
{Q_OBJECT
public:/*** @brief 构造函数* @param threadName 线程名称,用于标识* @param parent 父对象指针*/explicit WorkerThread(const QString &threadName, QObject *parent = nullptr);/*** @brief 析构函数 - 确保线程安全退出*/~WorkerThread();/*** @brief 安全停止线程*/void requestStop();signals:/*** @brief 线程状态更新信号* @param message 状态消息*/void statusUpdated(const QString &message);protected:/*** @brief 线程主执行函数*/void run() override;private:QString m_threadName; // 线程标识名称bool m_stopRequested; // 停止请求标志QMutex m_mutex; // 互斥锁保护共享数据
};#endif // WORKERTHREAD_H
workerthread.c
#include "workerthread.h"
#include <QDebug>
#include <QTime>
#include <QMutexLocker>WorkerThread::WorkerThread(const QString &threadName, QObject *parent): QThread(parent),m_threadName(threadName),m_stopRequested(false)
{qDebug() << "WorkerThread created:" << m_threadName;
}WorkerThread::~WorkerThread()
{// 确保线程安全退出requestStop();if(isRunning()){wait(500); // 等待500ms线程结束if(isRunning()){qWarning() << m_threadName << "thread not stopped properly, terminating!";terminate(); // 最后手段强制终止wait();}}qDebug() << "WorkerThread destroyed:" << m_threadName;
}void WorkerThread::requestStop()
{QMutexLocker locker(&m_mutex);m_stopRequested = true;
}void WorkerThread::run()
{qDebug() << m_threadName << "thread started";emit statusUpdated(m_threadName + ": 线程启动");int taskCount = 0;while(true){// 检查停止请求(线程安全方式){QMutexLocker locker(&m_mutex);if(m_stopRequested) break;}// 模拟工作负载 (随机500-1500ms)int delay = 500 + (qrand() % 1000);msleep(delay);// 更新状态++taskCount;QString msg = QString("%1: 完成任务 #%2 (耗时%3ms)").arg(m_threadName).arg(taskCount).arg(delay);emit statusUpdated(msg);}emit statusUpdated(m_threadName + ": 线程停止");qDebug() << m_threadName << "thread finished";
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QPushButton>
#include <QVBoxLayout>
#include <QVector>
#include "workerthread.h"
#include <QLabel>/*** @brief 主窗口类** 演示如何管理多个工作线程并与UI交互*/
class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:// 启动所有线程void startAllThreads();// 停止所有线程void stopAllThreads();// 更新线程状态显示void updateThreadStatus(int threadId, const QString &message);private:// 初始化UI组件void initUI();// 初始化工作线程void initThreads();// 连接信号槽void connectSignals();// UI组件QVector<QLabel*> m_statusLabels; // 线程状态标签QPushButton* m_startButton; // 启动按钮QPushButton* m_stopButton; // 停止按钮QVBoxLayout* m_mainLayout; // 主布局// 线程管理QVector<WorkerThread*> m_threads; // 工作线程集合static const int THREAD_COUNT = 3; // 线程数量
};#endif // MAINWINDOW_H
mianwindow.c
#include "mainwindow.h"
#include <QVBoxLayout>
#include <QWidget>
#include <QDebug>
#include <QPushButton>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent),m_startButton(nullptr),m_stopButton(nullptr),m_mainLayout(nullptr)
{// 设置窗口属性setWindowTitle("QT5.12 多线程演示");resize(500, 350);// 初始化UIinitUI();// 初始化线程initThreads();// 连接信号槽connectSignals();
}MainWindow::~MainWindow()
{// 停止并删除所有线程stopAllThreads();qDeleteAll(m_threads);m_threads.clear();
}void MainWindow::initUI()
{// 创建中央部件QWidget *centralWidget = new QWidget(this);setCentralWidget(centralWidget);// 创建主布局m_mainLayout = new QVBoxLayout(centralWidget);m_mainLayout->setSpacing(10);m_mainLayout->setContentsMargins(15, 15, 15, 15);// 创建状态标签for (int i = 0; i < THREAD_COUNT; ++i){QLabel *label = new QLabel(QString("线程 %1: 等待启动").arg(i+1), this);label->setStyleSheet("QLabel { font-weight: bold; }");m_statusLabels.append(label);m_mainLayout->addWidget(label);}// 添加弹性空间m_mainLayout->addStretch();// 创建控制按钮m_startButton = new QPushButton("启动所有线程", this);m_startButton->setFixedHeight(35);m_stopButton = new QPushButton("停止所有线程", this);m_stopButton->setFixedHeight(35);m_stopButton->setEnabled(false);// 添加按钮到布局m_mainLayout->addWidget(m_startButton);m_mainLayout->addWidget(m_stopButton);
}void MainWindow::initThreads()
{// 创建指定数量的工作线程for (int i = 0; i < THREAD_COUNT; ++i){WorkerThread *thread = new WorkerThread(QString("线程 %1").arg(i+1), this);m_threads.append(thread);}
}void MainWindow::connectSignals()
{// 连接按钮信号connect(m_startButton, &QPushButton::clicked,this, &MainWindow::startAllThreads);connect(m_stopButton, &QPushButton::clicked,this, &MainWindow::stopAllThreads);// 连接线程信号for (int i = 0; i < m_threads.size(); ++i){// 使用lambda捕获线程IDconnect(m_threads[i], &WorkerThread::statusUpdated,this, [this, i](const QString &msg){updateThreadStatus(i, msg);});}
}void MainWindow::startAllThreads()
{for (int i = 0; i < m_threads.size(); ++i){if (!m_threads[i]->isRunning()){m_threads[i]->start();}}// 更新按钮状态m_startButton->setEnabled(false);m_stopButton->setEnabled(true);
}void MainWindow::stopAllThreads()
{for (auto thread : m_threads){if (thread->isRunning()){thread->requestStop();}}// 更新按钮状态m_startButton->setEnabled(true);m_stopButton->setEnabled(false);
}void MainWindow::updateThreadStatus(int threadId, const QString &message)
{if (threadId >= 0 && threadId < m_statusLabels.size()){m_statusLabels[threadId]->setText(message);}
}
main.c
#include "mainwindow.h"#include <QApplication>
#include <QTime>int main(int argc, char *argv[])
{// 设置应用程序属性QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);QApplication app(argc, argv);// 设置随机种子qsrand(QTime::currentTime().msec());// 创建并显示主窗口MainWindow window;window.show();return app.exec();
}
相关文章:
Qt多线程学习初级指南
一、引言部分 1. 多线程编程的重要性 在当今计算环境中,多线程编程已成为开发高性能应用程序的关键技术。现代应用程序面临着三大挑战: GUI响应性:用户界面需要保持流畅响应,即使在进行后台计算时 多核利用率:随着多…...
《解锁vLLM:大语言模型推理的加速密码》
《解锁vLLM:大语言模型推理的加速密码》 引言:AI 时代的推理引擎之光 在当今的人工智能领域,大语言模型无疑是最为耀眼的明星。它们犹如智能世界的基石,为无数的应用和创新提供了强大的支持。从日常的智能聊天机器人,到复杂的文本生成、机器翻译任务,大语言模型都展现出…...
1.1 java开发的准备工作
准备工作 一.JDK 开始写java程序之前需要安装jdk jdk是java开发工具,包含着JRE和里面的JVM(虚拟机,可以使得不同环境下都能运行Java程序),和开发工具。 二.了解写程序的三大步骤步骤 java成功运行主要需要经过代码编写,编译&a…...
矩阵运算 第30次CCF-CSP计算机软件能力认证
n和d差距这么大 就可以想到改变矩阵运算顺序来解决这道题 假设两个矩阵,分别为a行b列与b行c列,那么一次矩阵运算复杂度是a乘以c乘以b,对于这题,如果从左往右运算复杂度将会到 1e4乘以1e4乘以20>1e9 (n1e4,d20),常识…...
【Tools】Git常见操作
Git 1 配置 包括: 用户信息、分支策略、合并策略、钩子脚本路径等。 git config -l # 等价 --local --list git config --global --list # 全局 git config --local --list # 当前仓库git config user.name git config user.emailgit config user.name "Your Name"…...
国产RK3568+FPGA以 “实时控制+高精度采集+灵活扩展” 为核心的解决方案
RK3568FPGA方案在工业领域应用的核心优势 一、实时性与低延迟控制 AMP架构与GPIO中断技术 通过非对称多处理架构(AMP)实现Linux与实时操作系统(RTOS/裸机)协同,主核负责调度,从核通过GPIO中断响应紧…...
UnoCSS原子CSS引擎-前端福音
UnoCSS是一款原子化的即时按需 CSS 引擎,其中没有核心实用程序,所有功能都是通过预设提供的。默认情况下UnoCSS应用通过预设来实现相关功能。 UnoCSS中文文档: https://www.unocss.com.cn 前有很多种原子化的框架,例如 Tailwind…...
0.(新专栏目录)数据分类的艺术:从理论到实践的全面指南
前言 话说天下大数据事,分久必合,合久必分。在这个数据爆炸的时代,我们见证了数据的分散与聚合,见证了数据从孤岛到互联的转变。 回望数据发展的历程,最初企业的数据系统往往是各自为政的,各部门、各系统…...
leetcode 二分查找应用
34. Find First and Last Position of Element in Sorted Array 代码: class Solution { public:vector<int> searchRange(vector<int>& nums, int target) {int low lowwer_bound(nums,target);int high upper_bound(nums,target);if(low high…...
航电系统之编队运动控制技术篇
航电系统的编队运动控制技术是现代航空航天领域的关键技术之一,涉及多飞行器协同飞行中的导航、通信、控制与决策。 一、技术原理 编队运动控制技术的核心目标是通过航电系统实现多飞行器(如无人机、卫星等)在空间或时间上的协同运动。其基本…...
Elasticsearch(ES)中的脚本(Script)
文章目录 一. 脚本是什么?1. lang(脚本语言)2. source(脚本代码)3. params(参数)4. id(存储脚本的标识符)5. stored(是否为存储脚本)6. script 的…...
Collection集合,List集合,set集合,Map集合
文章目录 集合框架认识集合集合体系结构Collection的功能常用功能三种遍历方式三种遍历方式的区别 List集合List的特点、特有功能ArrayList底层原理LinkedList底层原理LinkedList的应用场list:电影信息管理模块案例 Set集合set集合使用哈希值红黑树HashSet底层原理HashSet集合元…...
Kafka 核心使用机制总结
Kafka 核心使用机制总结 Kafka 核心使用机制总结1. 分区 (Partitions) - 实现伸缩性与并行处理2. 副本 (Replicas) / 复制因子 (Replication Factor) - 实现高可用与容错3. 消费者组 (Consumer Groups) - 控制消息分发与消费进度4. 数据保留策略 (Retention Policies) - 管理存…...
【MCP】第二篇:IDE革命——用MCP构建下一代智能工具链
【MCP】第二篇:IDE革命——用MCP构建下一代智能工具链 一、引言二、IDE集成MCP2.1 VSCode2.1.1 安装VSCode2.1.2 安装Cline2.1.3 配置Cline2.1.4 环境准备2.1.5 安装MCP服务器2.1.5.1 自动安装2.1.5.2 手动安装 2.2 Trae CN2.2.1 安装Trae CN2.2.2 Cline使用2.2.3 内…...
WebSocket是h5定义的,双向通信,节省资源,更好的及时通信
浏览器和服务器之间的通信更便利,比http的轮询等效率提高很多, WebSocket并不是权限的协议,而是利用http协议来建立连接 websocket必须由浏览器发起请求,协议是一个标准的http请求,格式如下 GET ws://example.com:3…...
【PostgreSQL教程】PostgreSQL 特别篇之 语言接口连接Perl
博主介绍:✌全网粉丝22W+,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物联网、机器学习等设计与开发。 感兴趣的可…...
springboot-基于Web企业短信息发送系统(源码+lw+部署文档+讲解),源码可白嫖!
摘要 当今社会已经步入了科学技术进步和经济社会快速发展的新时期,国际信息和学术交流也不断加强,计算机技术对经济社会发展和人民生活改善的影响也日益突出,人类的生存和思考方式也产生了变化。本系统采用B/S架构,数据库是MySQL…...
Centos9安装docker
1. 卸载docker 查看是否安装了docker yum list | grep docker卸载老版本docker,拷贝自官网 sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine卸载新版本…...
MySQL表的操作
MySQL表的操作 1. 创建表 在创建表前,需要先进入到某个数据库: use db_name创建表时,最好提前设计好表应该有的所有内容,否则后续添加或删除表的列可能会引发一连串的问题。 create table tb_name (field1 data_type [comment…...
Jmeter中同步定时器使用注意点
1.设置数量不可大于总线程数量,不然会一直等待 2.设置数量必须与总线程数量成整数倍数,不然还是要一直等。 3.当配置的数量小于线程数时,最好把循环打开,避免最后一次未准备好的线程数量达不到并发数。...
从零开始搭建Django博客③--前端界面实现
本文主要在Ubuntu环境上搭建,为便于研究理解,采用SSH连接在虚拟机里的ubuntu-24.04.2-desktop系统搭建,当涉及一些文件操作部分便于通过桌面化进行理解,通过Nginx代理绑定域名,对外发布。 此为从零开始搭建Django博客…...
使用Handsontable实现动态表格和下载表格
1.效果 2.实现代码 首先要加载Handsontable,在示例中我是cdn的方式引入的,vue的话需要下载插件 let hot null;var exportPlugin null;function showHandsontable(param) {const container document.getElementById("hot-container");// 如果…...
结合地理数据处理
CSV 文件不仅可以存储表格数据,还可以与地理空间数据结合,实现更强大的地理处理功能。例如,你可以将 CSV 文件中的坐标数据转换为点要素类,然后进行空间分析。 示例:将 CSV 文件中的坐标数据转换为点要素类 假设我们有…...
使用Geotools实现将Shp矢量文件加载SLD并合并图例生成-以湖南省周边城市为例
目录 前言 一、技术实现简介 1、生成成果说明 2、生成流程图说明 二、具体生成实践 1、渲染地图 2、生成图例 3、合并图像及输出 三、总结 前言 在当今数字化时代,地理信息系统(GIS)技术已成为城市管理、资源规划、环境监测等众多领域…...
openGauss数据库:起源、特性与对比分析
openGauss数据库:起源、特性与对比分析 一、起源与发展历程 1. 技术背景与开源历程 openGauss是由华为公司主导开发的开源关系型数据库管理系统,其技术根源可追溯至PostgreSQL。2019年,华为在内部整合了多个数据库产品线(如GMDB…...
相机中各个坐标系的转换关系如像素坐标系到世界坐标系以及相机标定的目的
一、背景 无论是机器人领域、SLAM还是自动驾驶领域,都会涉及相机标定,但是看了很多博客,都是各种坐标系的变换,没有从上层说明进行坐标变换的目的是什么,以及相机标定完成后,是已知像素坐标求世界坐标&…...
ubuntu24设置拼音输入法,解决chrome不能输入中文
## 推荐方案:使用 Fcitx5 Fcitx5 是当前在 Wayland 环境下兼容性最好的输入法框架。 ### 1. 安装 Fcitx5 bash sudo apt update sudo apt install fcitx5 fcitx5-chinese-addons fcitx5-frontend-gtk3 fcitx5-frontend-gtk4 fcitx5-frontend-qt5 fcitx5-module-c…...
linux内核进程管理(1)——创建,退出
linux源码阅读——进程管理(1) 1. 进程的基本介绍1.1 linux中进程和线程的区别1.2 task_struct中的基本内容1.3 命名空间ns(namespace)命名空间结构图Linux 中的命名空间类型 1.4 进程标识符 2. 创建一个进程的流程2.1 CLONE宏2.2 创建进程系统调用1. do…...
容器修仙传 我的灵根是Pod 第8章 护山大阵(DaemonSet)
第三卷:上古遗迹元婴篇 第8章 护山大阵(DaemonSet) 九霄之上,雷云如怒海翻腾。 天调度宗的护山大阵「九霄雷光阵」正发出悲鸣,七十二根镇山雷柱已有半数熄灭。每根雷柱底部,本该守护节点的「雷符傀儡」&a…...
使用Python将YOLO的XML标注文件转换为TXT文件格式
使用Python将YOLO的XML标注文件转换为TXT文件格式,并划分数据集 import xml.etree.ElementTree as ET import os from os import listdir, getcwd from os.path import join import random from shutil import copyfile from PIL import Image# 只要改下面的CLASSE…...
在面试中被问到spring是什么?
Spring框架的核心回答 1. 定义与定位 Spring是一个轻量级、开源的企业级应用开发框架,旨在简化Java应用的开发,提供全面的编程和配置模型。它的核心目标是解决企业应用开发的复杂性,通过模块化设计和松耦合架构,帮助开发者更高效…...
MongoDB Ubuntu 安装
MongoDB 安装 https://www.mongodb.com/zh-cn/docs/manual/installation/ https://www.mongodb.com/zh-cn/docs/manual/tutorial/install-mongodb-on-ubuntu/ https://www.mongodb.com/zh-cn/docs/manual/reference/ulimit/ https://www.mongodbmanager.com/download ubun…...
ElasticSearch深入解析(三):Elasticsearch 7的安装与配置、Kibana安装
文章目录 〇、简介1.Elasticsearch简介2.典型业务场景3.数据采集工具4.名词解释 一、安装1.使用docker(1)创建虚拟网络(2)Elasticsearch安装步骤 2.使用压缩包 二、配置1.目录介绍2.配置文件介绍3.elasticsearch.yml节点配置4.jvm.options堆配置问题:为什么说堆内存…...
初始SpringBoot
此文介绍一些有关我对SpringBoot的学习理解, 声明:此处我的IDEA是企业版的,可能和社区版会有一些差异 1. 第⼀个SpringBoot程序 1. SpringBoot介绍 我们看下Spring官方的介绍 可以看到,Spring让Java程序更加快速,简单和安全.Spring对于速…...
【算法笔记】动态规划基础(一):dp思想、基础线性dp
目录 前言动态规划的精髓什么叫“状态”动态规划的概念动态规划的三要素动态规划的框架无后效性dfs -> 记忆化搜索 -> dp暴力写法记忆化搜索写法记忆化搜索优化了什么?怎么转化成dp?dp写法 dp其实也是图论首先先说结论:状态DAG是怎样的…...
C++入门基础(2)
Hello~,欢迎大家来到我的博客进行学习! 目录 1.缺省参数2.函数重载3.引用3.1 引用的概念和定义3.2 引用的特性3.3引用的使用3.4 const引用3.5 指针和引用的关系扩展 4. nullptr 1.缺省参数 缺省参数是声明或定义函数时为函数的参数指定⼀个缺省值。在调用该函数时&…...
OpenCV-Python (官方)中文教程(部分一)_Day15
18.图像梯度 梯度简单来说就是求导。 OpenCV 提供了三种不同的梯度滤波器,或者说高通滤波器:Sobel, Scharr和Laplacian。Sobel,Scharr 其实就是求一阶或二阶导数。Scharr 是对 Sobel(使用小的卷积核求解求解梯度角度时)的优化。Laplacian 是…...
大厂面试:MySQL篇
前言 本章内容来自B站黑马程序员java大厂面试题和小林coding 博主学习笔记,如果有不对的地方,海涵。 如果这篇文章对你有帮助,可以点点关注,点点赞,谢谢你! 1.MySQL优化 1.1 定位慢查询 定位 一个SQL…...
软件工程的13条“定律”:从Hyrum定律到康威定律,再到Zawinski定律
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
Linux删除大文件df空间avail空间不增加
背景 根磁盘被同事写满,使用> 删除一些安装包后,df中的avail空间还是0 排除有进程正在占用文件,已使用lsof命令检测过我所删的文件是没有进程在使用 原因 是文件系统预留空间在作祟 解决 # 文件系统预留块 tune2fs -l /dev/vda2 | gr…...
【C语言-选择排序算法】实现对十个数进行排序
目录 前言 一、选择排序算法原理 二、选择排序算法实现对十个数进行排序 三、代码运行示例 四、选择排序算法的时间复杂度和空间复杂度分析 五、选择排序算法的优缺点 六、总结 前言 在计算机科学领域,排序算法是基石般的存在,它们就像是整理杂乱…...
驱动开发硬核特训 · Day 18:深入理解字符设备驱动与子系统的协作机制(以 i.MX8MP 为例)
日期:2025年04月23日 回顾:2025年04月22日(Day 17:Linux 中的子系统概念与注册机制) 本日主题:字符设备驱动 子系统协作机制剖析 学习目标:理解字符设备的注册原理,掌握其与子系统间…...
SQL Server 2022 常见问题解答:从安装到优化的全场景指南
SQL Server 2022 作为微软最新的数据库管理系统,在性能、安全性和云集成方面带来了多项革新。然而,用户在实际使用中仍可能遇到各类问题。本文将围绕安装配置、性能优化、备份恢复、安全设置、高可用性方案、兼容性问题及错误代码解析等核心场景…...
软件开发版本库命名规范说明
背景:近期一直再更新自己所开发的一个前端大文件上传npm库(enlarge-file-upload),为了让库的发版更加规范,于是参考了各种文档写下了这篇关于软件开发库的版本命名规范,且不仅局限于前端的版本命名规范,适用于整个软件…...
Kafka 详解
1.基本概念:Kafka 是分布式发布 - 订阅消息系统,具有高吞吐量、可扩展性等优势,支持点对点和发布订阅两种消息模式,涉及 Broker、Topic、Partition 等多种角色。 2.安装步骤:需先安装 JDK 和 Zookeeper,下…...
【Qwen2.5-VL 踩坑记录】本地 + 海外账号和国内账号的 API 调用区别(阿里云百炼平台)
API 调用 阿里云百炼平台的海内外 API 的区别: 海外版:需要进行 API 基础 URL 设置国内版:无需设置。 本人的服务器在香港,采用海外版的 API 时,需要进行如下API端点配置 / API基础URL设置 / API客户端配置…...
硬核解析:整车行驶阻力系数插值计算与滑行阻力分解方法论
引言:阻力优化的核心价值 在汽车工程领域,行驶阻力是影响动力性、经济性及排放的核心因素。根据统计,车辆行驶中约60%的燃油消耗用于克服阻力(风阻、滚阻、传动内阻等)。尤其在电动化趋势下,阻力降低1%可提…...
【网络原理】TCP提升效率机制(一):滑动窗口
目录 一. 前言 二. 滑动窗口 三. 丢包现象 1)ACK报文丢失 2)数据丢失 四. 总结 一. 前言 TCP最核心的机制就是可靠传输 ,确认应答,超时重传,连接管理这些都保证了可靠传输,得到了可靠传输,…...
移动端使用keep-alive将页面缓存和滚动缓存具体实现方法 - 详解
1. 配置组件名称 确保列表页组件设置了name选项,(组合式API额外配置): <!-- vue2写法 --> export default {name: UserList // 必须与 <keep-alive> 的 include 匹配 }<!-- vue3写法 --> defineOptions({na…...
工作记录9
1.点击按钮发送AJAX请求 <!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title&…...