【C++】线程池
C++ 线程池介绍
- 什么是线程池?
线程池(Thread Pool) 是一种并发编程模型,用于管理和复用多个线程,避免频繁创建/销毁线程的开销。它通过预创建一组线程,并将任务提交到队列中,由空闲线程自动执行,从而提升多线程程序的性能和资源利用率。
- 为什么需要线程池?
- 降低开销:线程创建/销毁成本高(涉及系统调用、内存分配)。
- 任务调度优化:避免线程竞争CPU导致的上下文切换损耗。
- 资源管控:限制并发线程数量,防止系统过载。
- 简化编程:将任务提交与执行逻辑解耦。
适用场景:
高并发服务器、批量数据处理、异步任务执行(如日志写入)、GUI后台计算等。
单队列线程池
简单高效,推荐使用!!!
实现
以下是基于C++11/17标准库的线程池简化实现:
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <future>class ThreadPool {
public:explicit ThreadPool(size_t num_threads = std::thread::hardware_concurrency()) {for (size_t i = 0; i < num_threads; ++i) {workers.emplace_back([this] {while (true) {std::function<void()> task;{std::unique_lock<std::mutex> lock(queue_mutex);condition.wait(lock, [this] { return stop || !tasks.empty(); });if (stop && tasks.empty()) return;task = std::move(tasks.front());tasks.pop();}task(); // 执行任务}});}}template<typename F, typename... Args>auto enqueue(F&& f, Args&&... args) -> std::future<decltype(f(args...))> {using return_type = decltype(f(args...));auto task = std::make_shared<std::packaged_task<return_type()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));std::future<return_type> res = task->get_future();{std::unique_lock<std::mutex> lock(queue_mutex);if (stop) throw std::runtime_error("enqueue on stopped ThreadPool");tasks.emplace([task] { (*task)(); });}condition.notify_one(); // 唤醒一个线程return res;}~ThreadPool() {{std::unique_lock<std::mutex> lock(queue_mutex);stop = true;}condition.notify_all();for (std::thread& worker : workers) {if (worker.joinable()) worker.join();}}private:std::vector<std::thread> workers;std::queue<std::function<void()>> tasks;std::mutex queue_mutex;std::condition_variable condition;bool stop = false;
};
线程池核心组件
组件 | 作用 |
---|---|
任务队列 | 存储待执行的任务(std::queue<std::function<void()>> ) |
工作线程组 | 预创建的线程集合,循环从队列中取任务执行(std::vector<std::thread> ) |
互斥锁 | 保护任务队列的线程安全访问(std::mutex ) |
条件变量 | 协调线程的休眠与唤醒(std::condition_variable ) |
停止标志 | 安全终止所有线程(bool stop ) |
使用示例
#include <iostream>int main() {ThreadPool pool(4); // 创建4个线程的线程池// 提交多个任务std::vector<std::future<int>> results;for (int i = 0; i < 8; ++i) {results.emplace_back(pool.enqueue([i] {std::this_thread::sleep_for(std::chrono::seconds(1));return i * i;}));}// 获取结果for (auto&& result : results) {std::cout << result.get() << ' ';}std::cout << std::endl;return 0;
}
输出:0 1 4 9 16 25 36 49
(执行时间约2秒,4线程并行)
优化方向
- 动态扩缩容:根据任务负载动态调整线程数量。
- 任务优先级:支持优先级队列(如
std::priority_queue
)。 - 任务窃取:允许空闲线程从其他线程的任务队列窃取任务。
- 返回值处理:使用
std::future
和std::packaged_task
传递异步结果。 - 异常处理:捕获任务中的异常并传递到主线程。
注意事项
- 线程安全:确保任务队列的访问通过锁保护。
- 资源释放:析构时需等待所有任务完成,避免资源泄漏。
- 死锁风险:避免在任务中阻塞等待其他任务的结果。
- 性能调优:根据硬件核心数设置合理线程数(通常为
CPU核心数 + 1
)。
通过线程池,可以显著提升C++程序的并发性能,同时保持代码的简洁与可维护性。
双队列线程池
总体来说,不推荐!!!
线程池是否可以使用两个队列(空闲队列 & 工作队列)?
在传统线程池设计中,通常使用单个任务队列来管理待执行的任务,所有工作线程共享此队列,并通过条件变量协调任务的获取与执行。但根据实际需求,可以通过两个队列(空闲线程队列 + 工作线程队列)来优化管理,以下是详细分析:
对比
设计方式 | 单任务队列 | 双队列(空闲+工作) |
---|---|---|
核心思想 | 所有线程共享一个任务队列,竞争获取任务 | 显式区分空闲线程和工作线程,按需调度 |
线程状态管理 | 隐式(通过条件变量等待) | 显式(记录线程是否空闲) |
适用场景 | 通用场景,简单高效 | 需要动态扩缩容、优先级调度等复杂场景 |
实现复杂度 | 简单 | 较高(需维护线程状态和队列同步) |
双队列设计的意义
- 动态线程管理:
根据任务负载动态调整活跃线程数量,例如:- 当任务队列积压时,从空闲队列唤醒更多线程。
- 当任务减少时,将空闲线程挂起或释放,减少资源占用。
- 优先级调度:
允许为不同优先级的任务分配独立队列,结合线程状态实现更精细的调度。 - 避免过度竞争:
将空闲线程与工作线程分离,减少锁争用(例如:空闲队列单独管理)。
双队列实现示例
以下是一个基于空闲队列和工作队列的线程池框架:
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>class ThreadPool {
public:explicit ThreadPool(size_t max_threads) : max_threads(max_threads) {}void enqueue(std::function<void()> task) {{std::unique_lock<std::mutex> lock(task_mutex);tasks.push(std::move(task));}// 尝试唤醒空闲线程或创建新线程if (!idle_threads.empty()) {std::unique_lock<std::mutex> lock(idle_mutex);auto thread = idle_threads.front();idle_threads.pop();lock.unlock();thread->assign_task(); // 唤醒空闲线程} else if (active_threads < max_threads) {create_thread(); // 创建新线程}}private:size_t max_threads;size_t active_threads = 0;std::queue<std::function<void()>> tasks;std::mutex task_mutex;// 空闲线程队列(存储可复用的线程对象)std::queue<std::shared_ptr<WorkerThread>> idle_threads;std::mutex idle_mutex;class WorkerThread {public:void assign_task(std::function<void()> task) {{std::unique_lock<std::mutex> lock(mtx);current_task = std::move(task);has_task = true;}cv.notify_one();}void run() {while (true) {std::function<void()> task;{std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [&] { return has_task || terminate; });if (terminate) return;task = std::move(current_task);has_task = false;}task(); // 执行任务// 任务完成后,将自己放回空闲队列pool->return_to_idle(this);}}bool is_idle() const { return !has_task; }private:std::mutex mtx;std::condition_variable cv;std::function<void()> current_task;bool has_task = false;bool terminate = false;};void create_thread() {auto worker = std::make_shared<WorkerThread>();std::thread([worker] { worker->run(); }).detach();active_threads++;}void return_to_idle(WorkerThread* thread) {std::unique_lock<std::mutex> lock(idle_mutex);idle_threads.push(thread);}
};
双队列的优缺点
优点 | 缺点 |
---|---|
动态扩缩容:按需增加/减少活跃线程 | 实现复杂度高(需管理线程生命周期) |
减少锁竞争(空闲与工作线程分离) | 上下文切换可能增多(线程频繁唤醒/挂起) |
支持更复杂的调度策略(如优先级) | 内存占用更高(需维护额外队列) |
适用场景
- 突发性高负载:任务量波动大时,动态调整线程数量。
- 资源敏感环境:需严格控制线程数量(如嵌入式系统)。
- 任务优先级调度:高优先级任务优先分配空闲线程。
总结
- 单队列足够大多数场景:简单高效,推荐优先使用。
- 双队列适合特殊需求:当需要动态扩缩容、优先级调度或减少锁竞争时,可考虑双队列设计,但需权衡实现复杂度与性能收益。
根据具体需求选择设计,避免过度工程化!
相关文章:
【C++】线程池
C 线程池介绍 什么是线程池? 线程池(Thread Pool) 是一种并发编程模型,用于管理和复用多个线程,避免频繁创建/销毁线程的开销。它通过预创建一组线程,并将任务提交到队列中,由空闲线程自动执行…...
美团社招一面
美团社招一面 做题 1、面试题 <style> .outer{width: 100px;background: red;height: 100px; }.inner {width: 50px;height: 50px;background: green; }</style> <div class"outer"><div class"inner"></div> </div>…...
C++:BST、AVL、红黑树
C:BST、AVL、红黑树 二叉搜索树(BST)二叉平衡搜索树(AVL)红黑树(RBT)三者对比什么情况下使用?C 标准库中的使用总结 二叉搜索树(BST) 二叉搜索树(Binary Sea…...
算法笔记.染色法判断二分图
题目:(来自AcWing) 给定一个 n 个点 m 条边的无向图,图中可能存在重边和自环。 请你判断这个图是否是二分图。 输入格式 第一行包含两个整数 n 和 m。 接下来 m 行,每行包含两个整数 u 和 v,表示点 u …...
在 IDEA 中写 Spark 程序:从入门到实践
在大数据处理领域,Apache Spark 凭借其出色的性能和丰富的功能受到广泛欢迎。而 IntelliJ IDEA 作为一款功能强大的 Java 集成开发环境,为编写 Spark 程序提供了极大的便利。本文将详细介绍如何在 IDEA 中搭建 Spark 开发环境并编写运行 Spark 程序&…...
[Spring] Sentinel详解
🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏: 🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 🍕 Collection与…...
让数据优雅落地:用 serde::Deserialize 玩转结构体实体
前言 想象一下,服务器突然飞来一堆 JSON 数据,就像一群无头苍蝇冲进办公室,嗡嗡作响,横冲直撞。此刻,你的任务,就是把这群“迷路数据”安置进正确的格子里,分门别类,秩序井然,不混不乱,不漏一只。 好在 Rust 早就为我们备好瑞士军刀:serde::Deserialize。它不仅刀…...
【wpf】 WPF中实现动态加载图片浏览器(边滚动边加载)
WPF中实现动态加载图片浏览器(边滚动边加载) 在做图片浏览器程序时,遇到图片数量巨大的情况(如几百张、上千张),一次性加载所有图片会导致界面卡顿甚至程序崩溃。 本文介绍一种 WPF Prism 实现动态分页加…...
Flow原理
fun main() {runBlocking {launch {flow4.collect{println("---collect-4")}println("---flow4")}}val flow4 flow<Boolean>{delay(5000)emit(false) } 我们分析下整个流程 1.flow为什么之后在collect之后才会发送数据 2.collect的调用流程 我…...
业绩回暖、股价承压,三只松鼠赴港上市能否重构价值锚点?
在营收重返百亿俱乐部后,三只松鼠再度向资本市场发起冲击。 4月25日,这家坚果零食巨头正式向港交所递交上市申请书,若成功登陆港股,将成为国内首个实现“AH”双上市的零食品牌。 其赴港背后的支撑力,显然来自近期披露…...
基于大模型的胆总管结石全流程预测与临床应用研究报告
目录 一、引言 1.1 研究背景 1.2 研究目的与意义 1.3 研究方法和创新点 二、大模型在胆总管结石预测中的应用原理 2.1 大模型概述 2.2 模型构建的数据来源与处理 2.3 模型训练与优化 三、术前预测与准备 3.1 术前胆总管结石存在的预测 3.2 基于预测结果的术前检查方…...
QT—布局管理器之BoxLayout篇
1.布局管理器的概述 在Qt中,使用布局管理器的主要原因是它能够自动管理组件的大小和位置,从而实现灵活且动态的界面布局。布局管理器可以自动调整组件以适应窗口大小的变化,确保界面在不同分辨率和设备上都能保持良好的显示效果。这不仅减少了…...
如何在 IntelliJ IDEA 中编写 Speak 程序
在当今数字化时代,语音交互技术越来越受到开发者的关注。如果你想在 IntelliJ IDEA(一个强大的集成开发环境)中编写一个语音交互(Speak)程序,那么本文将为你提供详细的步骤和指南。 一、环境准备 在开始编…...
湖北理元理律师事务所:债务优化的法律机制与民生实践
在债务纠纷日益增多的社会背景下,合法、规范的债务管理服务成为民生需求的重要环节。湖北理元理律师事务所作为经国家司法局注册登记的债事服务机构,以法律为工具,探索出一套覆盖债务咨询、规划与风险防控的服务体系。 1.法律服务的专业化框…...
练习普通话,说话更有节奏
玲珑塔,塔玲珑,玲珑宝塔第一层,一张高桌四条腿, 一个和尚一本经。一个铙钹一口磬,一个木鱼一盏灯。 一个金玲,整四两,风儿一刮响哗愣。 玲珑塔,隔过两层数三层,三张高桌十…...
链表相关——Python实现
一、链表的创建及数据插入 示例代码: #1.定义一个结点类 class ListNode():def __init__(self,x,nextNone):self.valxself.nextnext #2.定义单链表 class LinkList():#2.1 创建一个头指针为空的链表def __init__(self,headNone):self.headNone#2.2 将数据插入链表…...
[OS_9] C 标准库和实现 | musl libc | offset
在你感觉有困难的时候,计算机 一定有解决办法 操作系统为我们提供了对象和操作它们的 API:我们学习了进程管理的 fork, execve, exit, waitpid;内存管理的 mmap;文件 (对象) 管理的 open, read, write, dup, close, pipe, …… 大…...
【氮化镓】质子辐照对 GaN-on-GaN PiN 二极管电导调制的影响
2025 年,中国科学技术大学的 Xuan Xie 等人采用实验研究的方法,深入探究了 10-MeV 和 50-MeV 质子辐照( fluence 最高达 11014 cm−2)对 kV 级垂直 GaN-on-GaN PiN 二极管的导电调制影响。研究背景在于空间应用中的功率电子电路易受质子、α 粒子和重离子等影响而降级甚至失…...
深入浅出限流算法(一):简单但有“坑”的固定窗口计数器
在现代分布式系统和 API 设计中,限流 (Rate Limiting) 是一个不可或缺的环节。它像一个尽职的门卫,保护着我们的服务资源,防止因突发流量或恶意攻击导致系统过载,同时也能确保资源的公平分配。 实现限流的算法多种多样࿰…...
项目上线流程梳理(Linux宝塔面板)
项目部署(Linux宝塔面板) 一、准备工作 1、 后端项目 梳理配置添加application-prod.yml使用maven进行打包生成jar包 2、前端项目 修改request.ts请求的后端端口(服务器地址)打包 二、服务器 1、服务器环境安装 2、初始化数…...
MCP Servers玩玩WebUI自动化
MCP Servers快速了解 一文搞懂 MCP Servers mcp server网站 https://mcpservers.orghttps://mcp.sohttps://glama.ai/mcp/servershttps://www.pulsemcp.com 一、安装&配置mcp clients mcp clients可以使用客户端(常见claude desktop,但claude需…...
永磁同步电机控制算法-转速环电流环SMC控制器
一、原理介绍 为改进传统PI转速环电流环控制器易超调、抗干扰性能差的问题,转速环采用一阶滑模控制器,电流环采用二阶滑模控制器。 二、仿真验证 在MATLAB/simulink里面验证所提算法,采用和实验中一致的控制周期1e-4,电机部分计…...
Nginx支持HTTP2/HTTP3的并用CURL测试
对比HTTP2和HTTP3 HTTP/3 相比 HTTP/2 的主要优势: 项目HTTP/2HTTP/3传输层基于 TCP( TLS)基于 QUIC(内置 TLS)建立连接速度慢,至少 2~3 次握手(TCP TLS)快,只需 1 次握…...
阅读MySQL实战45讲第11天
目录 引言: 基本原理 排序方式 索引排序 文件排序(File Sort) 优化建议 一、全字段排序 二、rowid 排序 如果 MySQL 认为排序的单行长度太大会怎么做呢? 1. 使用磁盘临时表 2. 分阶段排序 3. 产生警告或错误 三、全字段排序 VS ro…...
linux 使用nginx部署vue、react项目
前言 本文基于:操作系统 CentOS Stream 8 使用工具:Xshell8、Xftp8 1.安装依赖 安装gcc、gcc-c yum install gcc gcc-c -y安装pcre、pcre-devel yum install pcre pcre-devel -y安装zlib、zlib-devel yum install zlib zlib-devel -y安装openssl、…...
逆向设计——CWDM_splitter
一、创建结构 switchtolayout; selectall; delete;## SIM PARAMS num_wg = 4; wg_width = 0.5e-6; out_wg_dist = 1e-6; mode_width = 3*wg_width; total_wg_h = num_wg*wg_width + (num_wg-1)*out_wg_dist;opt_size_x=6e-6; opt_size_y=6e-6;size_x=opt_size_x+1e-6; size_y=o…...
单片机-89C51部分:7、中断
飞书文档https://x509p6c8to.feishu.cn/wiki/A5gcwyL5giq1JOkkcsscn8eLnzf 一、中断的作用 中断是为使单片机具有对外部或内部随机发生的事件实时处理而设置的,中断功能的存在,很大程度上提高了单片机处理外部或内部事件的能力。它也是单片机最重要的功…...
小波变换和图像的融合
看到一篇比较有趣的文章,是将小波变换融入到图像配准过程中。论文题目是Deformable medical image registration based on wavelet transform and linear attention。论文提出了一种基于小波变换和线性注意力的可变形医学图像配准方法,通过小波下采样模块…...
2799. 统计完全子数组的数目
给你一个由 正 整数组成的数组 nums 。 如果数组中的某个子数组满足下述条件,则称之为 完全子数组 : 子数组中 不同 元素的数目等于整个数组不同元素的数目。 返回数组中 完全子数组 的数目。 子数组 是数组中的一个连续非空序列。 示例 1ÿ…...
docker镜像构建常用参数
要退出出去ctrlpq,或者直接输入exit也可以直接退出 这样就生成了可以这么用,但安全性比较差,不利于审计 企业里构建的镜像这样: “.”是构建的地点是当前的意思;构建了一层在[2/2]RUN touch /leefile里面 发现有我…...
如何用postman进行批量操作
业务场景: 有些时候,我们会需要批量的将SAP B1系统中的几千条的数据删除或者取消单据,这个时候,一条条去操作,指定是到猴年马月了。SAP Business One本身提供了DTW这个工具,但是这个更新,可以操…...
【MCP】第三篇:Cline工具链路追踪——解码“协议引擎“的神经传导奥秘
【MCP】第三篇:Cline工具链路追踪——解码"协议引擎"的神经传导奥秘 一、引言二、CloudFlare AI Gateway2.1 核心定位2.2 核心能力2.3 与MCP协议逆向的深度契合 三、VSCode Cline与CloudFlare联调实战3.1 CloudFlare配置3.2 VSCode Cline配置3.3 联调实战…...
HTML标记语言_@拉钩教育【笔记】
目录 1.文本标签 2.格式化标签 3.图片标签 4.超链接标签 5.表格标签 6表单标签 6.1 6.2 6.3 7.行内框架(超链接内套一个页面) 8.多媒体标签(音/视频) 1.文本标签 2.格式化标签 3.图片标签 4.超链接标签 5.表格标签 6表单标签 6.1 6.2 6.3 7.行内框架(超链接内套一个…...
SDK游戏盾、高防IP、高防CDN三者的区别与选型指南
在网络安全防护领域,SDK游戏盾、高防IP和高防CDN是常见的解决方案,但各自的功能定位、技术实现和适用场景差异显著。本文将通过对比核心差异,帮助您快速理解三者特点并选择适合的防护方案。 一、核心功能定位 SDK游戏盾 功能核心:…...
C++中的格式化字符串
C中的格式化字符串 fmt 库简介 {fmt}是一个开源的、现代化的C格式化库,由Victor Zverovich创建。它提供了一种安全、快速且方便的字符串格式化方式,其设计理念受到了Python的str.format()的启发 fmt库的主要特点 易用性:使用简洁的语法&a…...
民办生从零学C的第十二天:指针(1)
每日励志:拼搏十年,征战沙场,不忘初心,努力成为一个浑身充满铜臭味的有钱人。 一.内存和地址 1.内存 计算机内存是一系列存储单元的集合,每个存储单元都有唯一的地址来标识。这些存储单元用于存储程序的数据和指令。…...
复习Vue136~180
1.使用create-vue创建项目 npm init vuelatest 项目目录和关键文件: new Vue() 创建一个应用实例 > createApp()、createRouter() createStore() 、将创建实例进行了封装,保证每个实例的独立封闭性。 禁用vue2的插件vuter 使用vue3的插件volar scrip…...
高炉项目中DeviceNET到Ethernet的转换奥秘
在工业自动化的世界中,高炉项目中的数据通信至关重要。其中DeviceNET和Ethernet作为两种主流的网络协议,扮演着不可或缺的角色。它们之间的转换不仅仅是技术上的桥梁,更是实现信息高效传递的关键。今天,我们就来揭开从DeviceNET到…...
awk之使用详解(Detailed Explanation of Using AWK)
awk使用详解 1. 入门 1.1 什么是 awk? ①Awk是一种文本处理工具,适用于处理结构化数据,例如表格数据。 ②它可以读取一个或多个文本文件,并执行模式扫描和处理等指定的操作。 ③基本逻辑涉及数据的提取,排序和计算…...
TDR阻抗会爬坡? 别担心,不是你的错,你只是不够了解TDR!
在背板系统或任何长走线设计里,你大概都碰过这画面: TDR 曲线一开始乖乖在 92 Ω,但越往末端、阻抗越爬越高,来到最高 97 Ω,心里瞬间凉半截 😒 ,「难不成... 板厂又翻车了吗?」 然…...
TypeScript之基础知识
基础知识 1. 基本类型 类型描述string字符串(如 "hello")number数字(整数或浮点数,支持二进制、八进制、十六进制)boolean布尔值(true/false)null空值(需显式声明&#x…...
SNMP协议之详解(Detailed Explanation of SNMP Protocol)
SNMP协议之详解 一、前言 SNMP,被形象地喻为网络世界大的工具箱,使他们能的“智慧守护者”,它为网络管理员装备了一套功能强够实现对网络设备状态的实时监控、性能数据的全面收集、远程配置的灵活管理以及故障事件的即时响应。借助SNMP&…...
机器学习-入门-线性模型(2)
机器学习-入门-线性模型(2) 3.4广义线性回归 一般形式: y g − 1 ( w T x b ) y g^{-1} \left( w^T x b \right) yg−1(wTxb) 单调可微的联系函数 (link function) 令 g ( ⋅ ) ln ( ⋅ ) g(\cdot) \ln (\cdot) g(⋅)ln(⋅) 则得到对数线性回归 ln …...
【问题】docker容器修改环境变量的方式
问题 启动n8n之后,docker容器提示: There is a deprecation related to your environment variables. Please take the recommended actions to update your configuration: 2025-04-28 09:20:08 - N8N_RUNNERS_ENABLED -> Running n8n without tas…...
基于 Spring Boot 瑞吉外卖系统开发(八)
基于 Spring Boot 瑞吉外卖系统开发(八) 自动填充公共字段 MyBatis-Plus公共字段自动填充,也就是在插入或者更新的时候为指定字段赋予指定的值,使用它的好处就是可以统一对这些字段进行处理,降低了冗余代码的数量。本…...
LeetCode热题100--560.和为K的子数组(前缀和)--中等
1.题目 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1: 输入:nums [1,1,1], k 2 输出:2 示例 2: 输入:nums […...
搭建 Spark YARN 模式集群指南
在大数据处理领域,Apache Spark 凭借其卓越的性能和易用性广受青睐。而 YARN(Yet Another Resource Negotiator)作为 Hadoop 的资源管理框架,能高效管理集群资源。将 Spark 与 YARN 结合,以 YARN 模式搭建集群…...
服务器部署,Nginx安装和配置
Nginx简介 Nginx是一款轻量级和高性能的web服务器、反向代理服务器和电子邮件代理服务器。你可以使用Nginx实现网页的部署,解决跨域问题实现邮件服务器,甚至Nginx也可以实现音视频推流拉流服务器,Nginx可以实现的功能远超你的想象࿰…...
Java后端接口调用拦截处理:注解与拦截器的实现
在Java开发中,对后端接口调用进行拦截处理是一种常见的需求,通常用于权限验证、Token校验、状态更新等操作。本文将围绕 Spring框架的拦截器(Interceptor)、Spring AOP(面向切面编程) 和 Spring Security 三…...
C++(初阶)(十四)——多态
多态 面向对象的其中一大特征。 多态多态的定义及构成多态的构成条件多态的实现条件多态的分类编译时多态性运行时的多态性 虚函数定义不能成为虚函数的函数 虚函数重写(覆盖)选择题虚函数重写的其他问题析构函数的重写override 和final关键字重载/重写…...