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

ZLMediaKit 源码分析——[5] ZLToolKit 中EventPoller之延时任务处理

系列文章目录

第一篇 基于SRS 的 WebRTC 环境搭建
第二篇 基于SRS 实现RTSP接入与WebRTC播放
第三篇 centos下基于ZLMediaKit 的WebRTC 环境搭建
第四篇 WebRTC学习一:获取音频和视频设备
第五篇 WebRTC学习二:WebRTC音视频数据采集
第六篇 WebRTC学习三:WebRTC音视频约束
第七篇 WebRTC学习四:WebRTC常规视觉滤镜
第八篇 WebRTC学习五:从视频中提取图片
第九篇 WebRTC学习六:MediaStream 常用API介绍
第十篇 WebRTC学习七:WebRTC 中 STUN 协议详解
ZLMediaKit源码分析——[1] 开篇:基础库 ZLToolKit 之 onceToken 源码分析
ZLMediaKit 源码分析——[2] 从 ZLToolKit 代码看 CPU 亲和性设计
ZLMediaKit 源码分析——[3] ZLToolKit 中EventPoller之网络事件处理
ZLMediaKit 源码分析——[4] ZLToolKit 中EventPoller之异步任务处理
ZLMediaKit 源码分析——[5] ZLToolKit 中EventPoller之延时任务处理


文章目录

  • 系列文章目录
  • 前言
  • 一、整体设计思路
  • 二、源码分析
    • 2.1 延时任务处理函数
    • 2.2 getMinDelay 函数
    • 2.3 flushDelayTask 函数
  • 三、延时任务触发用户接口函数doDelayTask
  • 四、设计亮点与启发
    • 4.1 并发性能优化
    • 4.2 可重复任务处理
    • 4.3 异步插入任务
  • 五、实际应用场景
    • 5.1 定时任务
    • 5.2 超时检测
  • 总结


前言

前面两篇文章中已经讲到了EventPoller中的网络事件处理机制和异步任务处理机制,有了前面两篇文章的IO框架和异步任务的基础,今天的延时任务的内容就比较容易理解了,今天我们就一鼓作气,把ZLMediaKit中延时任务的机制和实现细节分析一下,结束掉EventPoller的分析。


一、整体设计思路

EventPoller 中的延时任务处理主要基于一个有序的任务队列 _delay_task_map。这个队列以任务的执行时间戳作为键,以任务对象作为值,按照时间戳从小到大的顺序排列。通过这种方式,我们可以很方便地找到最近需要执行的任务。

在处理延时任务时,主要涉及三个关键函数:flushDelayTask、getMinDelay 和 doDelayTask以及数据结构std::multimap<uint64_t, DelayTask::Ptr> _delay_task_map,下面我们将分别对这三个函数和_delay_task_map进行详细分析。

二、源码分析

2.1 延时任务处理函数

void EventPoller::runLoop(bool blocked, bool ref_self) {if (blocked) {if (ref_self) {s_current_poller = shared_from_this();}_sem_run_started.post();_exit_flag = false;uint64_t minDelay;
#if defined(HAS_EPOLL)struct epoll_event events[EPOLL_SIZE];while (!_exit_flag) {minDelay = getMinDelay();startSleep();//用于统计当前线程负载情况int ret = epoll_wait(_event_fd, events, EPOLL_SIZE, minDelay ? minDelay : -1);sleepWakeUp();//用于统计当前线程负载情况if (ret <= 0) {//超时或被打断continue;}// ...其它处理代码}
#elif defined(HAS_KQUEUE)// ... 其他系统的处理代码
#else// ... 其他系统的处理代码
#endif //HAS_EPOLL} else {_loop_thread = new thread(&EventPoller::runLoop, this, true, ref_self);_sem_run_started.wait();}
}

与live555中在最后处理延时队列中的任务不一样,在ZLToolKit中会优先处理延时队列任务,在消息循环函数中会调用getMinDelay(),所有延时队列任务的处理将在这个函数里完成。

2.2 getMinDelay 函数

uint64_t EventPoller::getMinDelay() {// 查找最早延时任务auto it = _delay_task_map.begin();if (it == _delay_task_map.end()) {//没有剩余的定时器了return 0;}// 获取当前时间auto now = getCurrentMillisecond();// 如果最早任务的执行时间大于当前时间,说明所有任务都尚未到期,函数返回最早任务执行时间与当前时间的差值,即需要等待的时间。if (it->first > now) {//所有任务尚未到期return it->first - now; // 计算需要等待的时间}//执行已到期的任务并刷新休眠延时return flushDelayTask(now);
}

这里首先获取_delay_task_map 的首元素,_dealy_task_map定义是std::multimap<uint64_t, DelayTask::Ptr> _delay_task_map;‌ std::multimap是C++标准库中的一个容器,它存储的元素都是键值对,并且允许有重复的键‌。这与std::map不同,后者不允许有重复的键。那么这个函数的意义就很明确了:
1、查找最早延时任务,没有返回0;
2、如果所有任务都尚未到期,函数返回需要等待的时间;
3、执行已到期的任务并刷新休眠延时,返回下一个未到期任务执行时所需的最小延时时间。
我们接下来看下执行已到期的任务并刷新休眠延时 flushDelayTask(now)函数里面做了些什么事情。

2.3 flushDelayTask 函数

uint64_t EventPoller::flushDelayTask(uint64_t now_time) {// 交换任务队列,将当前任务转移到临时容器,避免处理期间阻塞新任务写入。decltype(_delay_task_map) task_copy; // 自动推导_delay_task_map类型,task_copy初始化为空task_copy.swap(_delay_task_map); // 交换 task_copy 和 _delay_task_map 的内容。task_copy 持有原来的 _delay_task_map 数据。_delay_task_map 变为空容器。// 处理到期任务‌:执行所有时间戳 ≤ now_time 的任务,并根据返回值决定是否重新调度。for (auto it = task_copy.begin(); it != task_copy.end() && it->first <= now_time; it = task_copy.erase(it)) {//已到期的任务try {auto next_delay = (*(it->second))();if (next_delay) {//可重复任务,更新时间截止线_delay_task_map.emplace(next_delay + now_time, std::move(it->second));}} catch (std::exception &ex) {ErrorL << "Exception occurred when do delay task: " << ex.what();}}// 合并新任务和未处理任务‌,确保未到期任务和新添加的重复任务保留在队列中。task_copy.insert(_delay_task_map.begin(), _delay_task_map.end());task_copy.swap(_delay_task_map);auto it = _delay_task_map.begin();if (it == _delay_task_map.end()) {//没有剩余的定时器了return 0;}//最近一个定时器的执行延时return it->first - now_time;
}

EventPoller::flushDelayTask(uint64_t now_time) 函数的主要功能是处理所有已到期的延时任务,并根据任务的返回值决定是否重新调度这些任务,最后返回距离下一个未到期任务执行所需的最小延时时间。

三、延时任务触发用户接口函数doDelayTask

延时任务的外部调用接口为doDelayTask, 所有想要添加一个延时任务,需要通过调用doDelayTask添加,传入第一个参数为需要延时的毫秒值,第二个参数为task 任务,task任务返回值为0时代表不再重复任务,否则为下次执行延时,如果任务中抛异常,那么默认不重复任务。doDelayTask的返回值为DelayTask::Ptr,定义为 using DelayTask = TaskCancelableImp<uint64_t(void)>;是一个可取消的任务,意味着在还没到任务执行之前是可以取消的。

EventPoller::DelayTask::Ptr EventPoller::doDelayTask(uint64_t delay_ms, function<uint64_t()> task) {DelayTask::Ptr ret = std::make_shared<DelayTask>(std::move(task));auto time_line = getCurrentMillisecond() + delay_ms; // 当前时间+需要延时执行的时间async_first([time_line, ret, this]() {//异步执行的目的是刷新select或epoll的休眠时间_delay_task_map.emplace(time_line, ret);});return ret;
}

该函数的主要功能是创建一个延时任务,将其添加到延时任务映射_delay_task_map中,该任务将在指定的延时时间(delay_ms)后执行。

四、设计亮点与启发

4.1 并发性能优化

通过使用任务队列交换的方式,避免了在处理任务时阻塞新任务的添加,提高了程序的并发性能。这种设计思路在处理高并发场景下的任务调度非常有效。

4.2 可重复任务处理

支持可重复执行的任务,通过任务返回的延时时间来重新调度任务,增加了任务处理的灵活性。这种设计使得程序可以方便地实现定时任务的功能。

4.3 异步插入任务

使用异步方式插入任务,确保了系统能够及时响应新的延时任务。这在网络编程中尤为重要,因为网络事件的处理需要高实时性。

五、实际应用场景

5.1 定时任务

可以使用 doDelayTask 函数来实现定时任务,例如定时清理缓存、定时发送心跳包等。
如zlToolKit中定时器的实现

Timer::Timer(float second, const std::function<bool()> &cb, const EventPoller::Ptr &poller) {_poller = poller;if (!_poller) {_poller = EventPollerPool::Instance().getPoller();}_tag = _poller->doDelayTask((uint64_t) (second * 1000), [cb, second]() {try {if (cb()) {//重复的任务return (uint64_t) (1000 * second);}//该任务不再重复return (uint64_t) 0;} catch (std::exception &ex) {ErrorL << "Exception occurred when do timer task: " << ex.what();return (uint64_t) (1000 * second);}});
}

这里Timer构造函数通过事件轮询器构建了一个定时任务,该任务会在指定的时间间隔后执行一个回调函数。根据回调函数的返回值,定时器可以选择重复执行或停止执行。同时,代码中对回调函数的异常进行了捕获和处理,确保在出现异常时定时器仍然可以继续运行。

5.2 超时检测

在网络通信中,经常需要检测连接是否超时。可以通过设置延时任务来实现超时检测,当任务到期时,如果连接还没有收到响应,则认为连接超时。
比如MediaSource.cpp 的findAsync_l函数中代码:

auto on_timeout = poller->doDelayTask(maxWaitMS, [cb_once, listener_tag]() {// 最多等待一定时间,如在这个时间内,流还未注册上,则返回空NoticeCenter::Instance().delListener(listener_tag, Broadcast::kBroadcastMediaChanged);cb_once(nullptr);return 0;});

这里如果在最大等待时间里没有找到媒体源,将触发超时回调。


总结

ZLToolKit 中的 EventPoller 提供了一套高效、灵活的延时任务处理机制。通过有序的任务队列、任务队列交换、异步插入任务等技术手段,保证了程序的高并发性能和实时性。在实际应用中,我们可以根据具体需求灵活运用这些功能,实现各种复杂的定时任务和超时检测功能。

希望通过本文的分析,大家能够对 ZLMediaKit 中 EventPoller 的延时任务处理机制有更深入的理解,并在自己的项目中借鉴其设计思路。

相关文章:

ZLMediaKit 源码分析——[5] ZLToolKit 中EventPoller之延时任务处理

系列文章目录 第一篇 基于SRS 的 WebRTC 环境搭建 第二篇 基于SRS 实现RTSP接入与WebRTC播放 第三篇 centos下基于ZLMediaKit 的WebRTC 环境搭建 第四篇 WebRTC学习一&#xff1a;获取音频和视频设备 第五篇 WebRTC学习二&#xff1a;WebRTC音视频数据采集 第六篇 WebRTC学习三…...

【51单片机】2-6【I/O口】电动车简易防盗报警器实现

1.硬件 51最小系统继电器模块震动传感器模块433M无线收发模块 2.软件 #include "reg52.h" #include<intrins.h> #define J_ON 1 #define J_OFF 0sbit switcher P1^0;//继电器 sbit D0_ON P1^1;//433M无线收发模块 sbit D1_OFF P1^2; sbit vibrate …...

windows下载安装远程桌面工具RealVNC-Server教程(RealVNC_E4_6_1版带注册码)

文章目录 前言一、下载安装包二、安装步骤三、使用VNC-Viewer客户端远程连接&#xff0c;输入ip地址&#xff0c;密码完成连接 前言 在现代工作和生活中&#xff0c;远程控制软件为我们带来了极大的便利。RealVNC - Server 是一款功能强大的远程控制服务器软件&#xff0c;通过…...

C语言的操作系统

C语言的操作系统 引言 操作系统是一种系统软件&#xff0c;它管理计算机硬件和软件资源&#xff0c;并为计算机程序提供公共服务。在现代计算机科学中&#xff0c;操作系统是不可或缺的组成部分&#xff0c;而C语言则是实现高效操作系统的主要编程语言之一。本文将探讨C语言在…...

selectdb修改表副本

如果想修改doris&#xff08;也就是selectdb数据库&#xff09;表的副本数需要首先确定是否分区表&#xff0c;当前没有数据字典得知哪个表是分区的&#xff0c;只能先show partitions看结果 首先&#xff0c;副本数不应该大于be节点数 其次&#xff0c;修改期间最好不要跑业务…...

leetcode数组-有序数组的平方

题目 题目链接&#xff1a;https://leetcode.cn/problems/squares-of-a-sorted-array/ 给你一个按 非递减顺序 排序的整数数组 nums&#xff0c;返回 每个数字的平方 组成的新数组&#xff0c;要求也按 非递减顺序 排序。 输入&#xff1a;nums [-4,-1,0,3,10] 输出&#xff…...

【python中级】关于Cython 的源代码pyx的说明

【python中级】关于Cython 的源代码pyx的说明 1.背景2.编译3.语法1.背景 Cython 是一个编程语言和工具链,用于将 Python 代码(或类 Python 的代码)编译成 C 语言,再进一步生成高性能的 Python 扩展模块(.so 或 .pyd 文件)。 在 Python 中,.pyx 文件是 Cython 的源代码文…...

开放最短路径优先 - OSPF【LSA详细】

目录 LSA的头部结构 LSA类型 LSA数据包 LSA的主要作用是传递路由信息。 LSA的头部结构 共占20个字节&#xff0c;不同类型的LSA头部字段部分都是相同的。 链路状态老化时间(Link-State Age) 2个字节。指示该条LSA的老化时间&#xff0c;即它存在了多长时间&#xff0c;单位…...

PyTorch:解锁AI新时代的钥匙

揭开PyTorch面纱 对于许多刚开始接触人工智能领域的朋友来说&#xff0c;PyTorch这个名字或许既熟悉又陌生。熟悉在于它频繁出现在各类技术论坛和新闻报道中&#xff1b;而陌生则源于对这样一个强大工具背后运作机制的好奇。简单来说&#xff0c;PyTorch是一个开源库&#xff…...

欧几里得算法求最大公约数、最小公倍数

这段代码就是不断用较小数和余数来更新 a 和 b&#xff0c;直到余数变为 0&#xff0c;最后返回的 a 就是最大公约数。 #include <iostream> using namespace std;//最大公约数 int gcd(int a, int b){//这个循环表示只要 b 不是 0&#xff0c;就继续进行。//因为当 b …...

QEMU源码全解析 —— 块设备虚拟化(14)

接前一篇文章:QEMU源码全解析 —— 块设备虚拟化(13) 本文内容参考: 《趣谈Linux操作系统》 —— 刘超,极客时间 《QEMU/KVM源码解析与应用》 —— 李强,机械工业出版社 特此致谢! 上一回开始解析VirtioDeviceClass的realize函数virtio_blk_device_realize(),再来回…...

深入理解AOP:面向切面编程的核心概念与实战应用

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…...

3500 阶乘求和

3500 阶乘求和 ⭐️难度&#xff1a;中等 &#x1f31f;考点&#xff1a;2023、思维、省赛 &#x1f4d6; &#x1f4da; import java.util.Scanner;public class Main {public static void main(String[] args) {long sum 0;for(int i1;i<50;i) { // 之后取模都相等su…...

正则入门到精通

​ 一、正则表达式入门​ 正则表达式本质上是一串字符序列&#xff0c;用于定义一个文本模式。通过这个模式&#xff0c;我们可以指定要匹配的文本特征。例如&#xff0c;如果你想匹配一个以 “abc” 开头的字符串&#xff0c;正则表达式可以写作 “^abc”&#xff0c;其中 …...

Mysql 行级锁在什么样的情况下会升级为表级锁?

在 MySQL 中&#xff0c;行级锁通常由 InnoDB 存储引擎使用&#xff0c;因为它支持高并发和细粒度的锁定。通常情况下&#xff0c;InnoDB 在执行诸如 UPDATE、DELETE 或 SELECT FOR UPDATE 等操作时&#xff0c;会为被修改的数据行加锁&#xff08;行级锁&#xff09;。但是&am…...

docker部署kkfileview

拉取 KKFileView 镜像 docker pull keking/kkfileview或指定版本 docker pull keking/kkfileview:4.1.0运行 KKFileView 容器 docker run -d \--name kkfileview \-p 8012:8012 \--restart always \keking/kkfileview-d&#xff1a;后台运行 -p 8012:8012&#xff1a;将容器…...

优选算法的妙思之流:分治——快排专题

专栏&#xff1a;算法的魔法世界 个人主页&#xff1a;手握风云 目录 一、快速排序 二、例题讲解 2.1. 颜色分类 2.2. 排序数组 2.3. 数组中的第K个最大元素 2.4. 库存管理 III 一、快速排序 分治&#xff0c;简单理解为“分而治之”&#xff0c;将一个大问题划分为若干个…...

蓝桥杯嵌入式第15届真题-个人理解+解析

个人吐槽 #因为最近蓝桥杯快要开始了&#xff0c;我舍不得米白费了&#xff0c;所以就认真刷刷模拟题&#xff0c;但是我感觉真题会更好&#xff0c;所以就看了一下上届的真题。不过它是真的长&#xff0c;我看着就头晕&#xff0c;但是还是把几个模块认真分析了一下就还是很容…...

数据库系统概述 | 第二章课后习题答案

本文为数据库系统概论&#xff08;第五版&#xff09;【高等教育出版社】部分课后答案 如有错误&#xff0c;望指正 &#x1f47b; 习题 &#x1f47b; 答案...

深入解析CPU主要参数:选购与性能评估指南

引言 中央处理器&#xff08;CPU&#xff09;作为计算机的"大脑"&#xff0c;其性能直接决定了整机的运算能力和响应速度。无论是组装新电脑、升级旧系统还是选购笔记本电脑&#xff0c;理解CPU的关键参数都至关重要。本文将从技术角度全面解析CPU的各项主要参数&am…...

Lettuce与Springboot集成使用

一、Lettuce核心优势与Spring Boot集成背景 Lettuce特性 基于Netty的非阻塞I/O模型&#xff0c;支持同步/异步/响应式编程线程安全&#xff1a;共享单连接实现多线程并发操作&#xff0c;性能衰减低原生支持Redis集群、哨兵、主从架构&#xff0c;自动重连机制保障高可用Spring…...

【Kafka基础】ZooKeeper在Kafka中的核心作用:分布式系统中枢神经系统

在分布式系统的世界里&#xff0c;协调和管理多个节点间的状态是一项复杂而关键的任务。Apache Kafka作为一款高性能的分布式消息系统&#xff0c;其设计哲学是"专为单一目的而优化"——即高效处理消息流。为了实现这一目标&#xff0c;Kafka选择将集群协调管理的重任…...

专业的情商测评工具:EQ-i在线测评系统

专业的情商测评工具&#xff1a;EQ-i在线测评系统 基于巴昂情商量表的专业情商评估工具&#xff0c;帮助您更好地了解自己的情商水平。 什么是EQ-i&#xff1f; EQ-i&#xff08;Emotional Quotient Inventory&#xff09;是由Reuven Bar-On开发的情商量表&#xff0c;是国际上…...

Ubuntu安装Podman教程

1、先修改apt源为阿里源加速 备份原文件&#xff1a; sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup 修改源配置&#xff1a; vim sources.list删除里面全部内容后&#xff0c;粘贴阿里源&#xff1a; deb http://mirrors.aliyun.com/ubuntu/ focal main re…...

7.训练篇5-毕设

使用23w张数据集-vit-打算30轮-内存崩了-改为batch_size 8 我准备用23w张数据集&#xff0c;太大了&#xff0c;这个用不了&#xff0c;所以 是否保留 .stack() 加载所有图片&#xff1f;情况建议✅ 小数据集&#xff08;<2w张&#xff0c;图像小&#xff09;想加快速度可…...

java数据结构-哈希表

什么是哈希表 最理想的搜索方法 , 即就是在查找某元素时 , 不进行任何比较的操作 , 一次直接查找到需要搜索的元素 , 可以达到这种要求的方法就是哈希表. 哈希表就是通过构造一种存储结构 , 通过某种函数使元素存储的位置与其关键码位形成一 一映射的关系 , 这样在查找元素的时…...

Linux错误(6)X64向量指令访问地址未对齐引起SIGSEGV

Linux错误(6)X64向量指令访问地址未对齐引起SIGSEGV Author: Once Day Date: 2025年4月4日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章可参考专栏: Linux实…...

SpringBoot配置文件多环境开发

目录 一、设置临时属性的几种方法 1.启动jar包时&#xff0c;设置临时属性 ​2.idea配置临时属性 3.启动类中创建数组指定临时属性 二、多环境开发 1.包含模式 2.分组模式 三、配置文件的优先级 1.bootstrap 文件优先&#xff1a; 2.特定配置文件优先 3.文件夹位置优…...

解锁健康密码:拥抱活力养生生活

在追求高品质生活的今天&#xff0c;健康养生成为了人们关注的焦点。它不仅关乎当下的生活质量&#xff0c;更是对未来的有力投资。 合理的饮食是健康养生的基石。一日三餐&#xff0c;应遵循 “五谷为养&#xff0c;五果为助&#xff0c;五畜为益&#xff0c;五菜为充” 的原则…...

手动将ModelScope的模型下载到本地

一、ModelScope 介绍 ModelScope 官网地址&#xff1a; https://www.modelscope.cn/home 模型库地址&#xff1a;https://www.modelscope.cn/models 文档中心&#xff1a;https://www.modelscope.cn/docs/home ModelScope旨在打造下一代开源的模型即服务共享平台&#xff0c;为…...

【Git】“warning: LF will be replaced by CRLF”的解决办法

一、原因分析 不同操作系统的换行符标准不同&#xff1a; • Windows&#xff1a;使用 CRLF&#xff08;\r\n&#xff09;表示换行&#xff1b; • Linux/Mac&#xff1a;使用 LF&#xff08;\n&#xff09;表示换行 Git 检测到本地文件的换行符与仓库设置或目标平台不兼容时…...

Linux常用基础命令应用

目录 一、文件与目录管理 1. ​​基础导航与查看​​ 2. ​​文件操作核心命令​​ 二、文本处理与日志分析 1. ​​查看与过滤​​ 2. ​​组合命令与管道​​ 三、系统管理与权限控制 1. ​​进程与资源监控​​ 2. ​​权限与用户管理​​ 四、网络与远程操作 1. …...

C++11可变参数模板单例模式

单例模式 该示例代码采用C11标准&#xff0c;解决以下问题&#xff1a; 通过类模板函数实现不同类型单例&#xff1b;单例类构造函数支持不同的个数&#xff1b;消除代码重复 示例代码 .h文件如下&#xff1a; //C11Singleton.h文件 #pragma oncetemplate <typename T&…...

JVM 有哪些垃圾回收器

垃圾收集算法 标记-复制算法(Copying): 将可用内存按容量划分为两个区域,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面, 然后再把已使用过的内存空间一次清理掉。 标记-清除算法(Mark-Sweep): 算法分为“标记” 和“清除”两个…...

6. 链式结构(Chain)的奥秘:从LLMChain到RouterChain

引言&#xff1a;从“单兵作战”到“流水线革命” 2023年某电商平台客服系统因处理复杂咨询需手动串联多个AI模块&#xff0c;平均响应时间长达12秒。引入LangChain链式架构后&#xff0c;工单处理速度提升8倍&#xff0c;错误率下降45%。本文将深入解析链式编程范式&#xff…...

TypeScript语言的操作系统原理

TypeScript语言的操作系统原理 引言 操作系统是计算机系统中最重要的组成部分之一&#xff0c;它为应用程序提供了一个运行环境&#xff0c;并管理着计算机硬件和软件资源。随着编程语言的发展&#xff0c;特别是TypeScript的流行&#xff0c;许多开发者开始探索将这种强类型…...

时间序列入门

时间序列入门 第一章 时间序列概述1.1 时间序列简介1.1.1 时间序列定义1.1.2 时间序列分量1.1.3 时间序列分类 第二章 时间序列绘图2.1 单变量时序绘制2.2 多变量时序绘制 第一章 时间序列概述 1.1 时间序列简介 1.1.1 时间序列定义 在进行时间序列之前&#xff0c;需要学习…...

VirtualBox安装FnOS

1.下载FnOS镜像 下载网址&#xff1a; https://www.fnnas.com/2.创建虚拟机 虚拟机配置如图所示&#xff08;注意操作系统类型和网卡配置&#xff09; &#xff08;注意启动顺序&#xff09; 3.启动虚拟机 网卡类型选择桥接的Virtual Adapter 如果没有IP地址或者IP地址无法…...

函数栈帧的创建与销毁

函数栈帧的创建与销毁 函数栈帧简介认识寄存器解析函数栈帧的创建与销毁 函数栈帧简介 我们在编程的过程中经常会听见函数栈帧这个词汇&#xff0c;那到底什么是函数栈帧呢&#xff1f;接下来就为大家解答一下&#xff0c;我们都知道&#xff0c;一个函数的创建是需要去开辟空…...

Scheme语言的算法

Scheme语言的算法探索 引言 Scheme是一种以表达式为基础的编程语言&#xff0c;属于Lisp家族&#xff0c;因其简洁、灵活的语法而受到广泛关注。Scheme不仅适合教学&#xff0c;还被用于实际应用开发和研究。本文将深入探讨Scheme语言的算法&#xff0c;包括其基本特性、常用…...

[C++面试] new、delete相关面试点

一、入门 1、说说new与malloc的基本用途 int* p1 (int*)malloc(sizeof(int)); // C风格 int* p2 new int(10); // C风格&#xff0c;初始化为10 new 是 C 中的运算符&#xff0c;用于在堆上动态分配内存并调用对象的构造函数&#xff0c;会自动计算所需内存…...

(回滚莫队)洛谷 P10268 符卡对决 题解

居然还没调出来&#xff1f;感觉是数据类型的问题&#xff0c;真是吓人。先把思路写一下吧。 题意 灵梦一共有 n n n 张符卡&#xff0c;每张卡都有一个能力值&#xff0c;对于第 i i i 张卡&#xff0c;它的能力值为 a i a_i ai​&#xff0c;现在她想从中选出两张符卡并…...

C语言复习笔记--指针(3)

接上篇文章C语言复习笔记--指针(2)-CSDN博客我们继续进行指针的复习. 二级指针 指针变量也是变量&#xff0c;是变量就有地址&#xff0c;那指针变量的地址取出来后要存在在什么变量中呢?这就是⼆级指针. ⼆级指针的运算见下: 指针数组 指针数组概念 既然要联系数组和指针就涉…...

Fastjson 处理 JSON 生成与解析指南

Fastjson 是阿里巴巴开源的高性能 JSON 库&#xff0c;适用于 Java 对象的序列化&#xff08;生成 JSON&#xff09;和反序列化&#xff08;解析 JSON&#xff09;。以下是详细使用指南&#xff1a; 1. 添加依赖 <dependency><groupId>com.alibaba</groupId>…...

深度学习数据集划分比例多少合适

在机器学习和深度学习中&#xff0c;测试集的划分比例需要根据数据量、任务类型和领域需求灵活调整。 1. 常规划分比例 通用场景 训练集 : 验证集 : 测试集 60% : 20% : 20% 适用于大多数中等规模数据集&#xff08;如数万到数十万样本&#xff09;&#xff0c;平衡了训练数…...

查询当前用户的购物车和清空购物车

业务需求&#xff1a; 在小程序用户端购物车页面能查到当前用户的所有菜品或者套餐 代码实现 controller层 GetMapping("/list")public Result<List<ShoppingCart>> list(){List<ShoppingCart> list shoppingCartService.shopShoppingCart();r…...

大模型如何引爆餐饮与电商行业变革

大模型如何引爆餐饮与电商行业变革&#xff1f; 一、时代背景&#xff1a;大模型重构产业逻辑的底层动力 1. 技术跃迁催生效率革命 2025年&#xff0c;大模型技术迎来"普惠临界点"。李开复在中关村论坛指出&#xff0c;大模型推理成本每年降低10倍&#xff0c;使得…...

【MySQL】01.MySQL环境安装

注意&#xff1a;在MYSQL的安装与卸载中&#xff0c;需要使用root用户进行。 一、卸载不必要的环境 • 查看是否有运行的服务 [rootVM-24-10-centos etc]# ps axj |grep mysql1 22030 22029 22029 ? -1 Sl 27 0:00 /usr/sbin/mysqld --daemonize --pid-fi…...

java 匿名内部类 和 Lambda 表达式

java 匿名内部类 和 Lambda 表达式 一、匿名内部类1.1说明1.2 匿名内部类的作用1.3 特点1.4 接口的正常使用情况&#xff08;抽象类同理&#xff09;1.5 通过局部内部类使用接口&#xff08;抽象类同理&#xff09;1.6 通过匿名内部类使用接口&#xff08;抽象类同理&#xff0…...

Linux系统调用编程

进程和线程 进程是操作系统资源分配的基本单位&#xff0c;拥有独立的地址空间、内存、文件描述符等资源&#xff0c;进程间相互隔离。每个进程由程序代码、数据段和进程控制块&#xff08;PCB&#xff09;组成&#xff0c;PCB记录了进程状态、资源分配等信息。 线程是…...