面试宝典(十七):手写线程池与定时器
0. 为什么需要线程池每次任务来都std::thread新建线程的代价创建成本高内核要分配 PCB、栈、调度结构约几十~上百微秒。数量失控突发流量下线程数爆炸上下文切换context switch开销反超业务。无管理无法限制并发度、无法队列化背压。线程池的核心思想预先起固定数量的 worker 线程任务以std::function形式入队worker 从队列取任务执行。达到线程复用 并发可控 队列削峰。1. 最简线程池条件变量版#includethread#includevector#includequeue#includemutex#includecondition_variable#includefunctional#includeiostreamclassThreadPool{public:explicitThreadPool(size_t n):stop_(false){for(size_t i0;in;i)workers_.emplace_back([this]{workerLoop();});}~ThreadPool(){{std::lock_guardstd::mutexlk(mtx_);stop_true;}cv_.notify_all();// 唤醒所有 worker 让其退出for(autot:workers_)t.join();// 等线程结束RAII 析构}// 提交任务无返回值版voidsubmit(std::functionvoid()task){{std::lock_guardstd::mutexlk(mtx_);tasks_.push(std::move(task));}cv_.notify_one();// 唤醒一个空闲 worker}private:voidworkerLoop(){while(true){std::functionvoid()task;{std::unique_lockstd::mutexlk(mtx_);// 用 while条件变量避免虚假唤醒stop_ 时无论队列空否都退出cv_.wait(lk,[this]{returnstop_||!tasks_.empty();});if(stop_tasks_.empty())return;taskstd::move(tasks_.front());tasks_.pop();}task();// 在锁外执行减小临界区}}std::vectorstd::threadworkers_;std::queuestd::functionvoid()tasks_;std::mutex mtx_;std::condition_variable cv_;boolstop_;};设计要点cv_.wait(lk, pred)的pred必须用while语义判断条件变量可能被虚假唤醒谓词里包含stop_保证退出信号也能唤醒。任务在锁外执行task()在unique_lock析构解锁之后调用避免持锁运行导致 worker 间串行化这是性能关键。析构函数先置stop_再notify_all再join保证所有 worker 干净退出不丢任务队列里剩余任务不再执行生产可改为drain 模式。2. 让 submit 有返回值std::future无返回值的池只能发了不管。用std::packaged_task把任务结果打包进std::future提交即可get()等待结果#includefuturetemplateclassFautosubmitWithResult(Ff)-std::futuredecltype(f()){usingRdecltype(f());autotaskstd::make_sharedstd::packaged_taskR()(std::forwardF(f));std::futureRfuttask-get_future();{std::lock_guardstd::mutexlk(mtx_);// packaged_task 不可拷贝用 lambda 包一层 shared_ptrtasks_.push([task]{(*task)();});}cv_.notify_one();returnfut;}用法auto r pool.submitWithResult([]{ return 12; }); r.get(); // 3。注意packaged_task不可拷贝必须存shared_ptr否则push进std::function会编译失败——这是高频坑。3. 任务异常怎么办若task()抛异常异常会在future.get()处重新抛出因为packaged_task捕获了异常进 future。但无返回值版submit直接task()抛异常会终止整个 worker 线程std::thread 析构时std::terminate。生产级做法worker 里包一层try/catch或统一要求任务自身不抛异常。面试常问任务抛异常会怎样——务必答清两条路径差异。4. 线程数怎么定经典经验公式CPU 密集型线程数 ≈ 核数std::thread::hardware_concurrency()多了只增加切换。I/O 密集型线程数可远大于核数公式 ≈ 核数 × (1 等待时间/计算时间)。靠压测调优。更高级的做法是分离线程池CPU 池核数个 I/O 池较多避免慢 I/O 阻塞计算任务。5. 无锁任务队列进阶std::queue mutex在超高并发提交时会成为瓶颈。可用MPMC多生产者多消费者无锁队列如 moodycamel::ConcurrentQueue或自己用 atomic 实现。核心思想用 CAS 维护头尾指针、每个节点独立、避免全局锁。本篇不展开完整 MPMC 实现见 S04 无锁环形队列的 SPSC 思路但面试要知道高吞吐线程池可换无锁队列。6. 定时器最小堆实现服务器需要300ms 后检查连接是否存活“每 5s 上报一次”。用**最小堆按到期时间排序**管理定时任务由一个 timer 线程wait_until(最近到期时刻)到点执行并重新入堆#includechrono#includequeue#includemutex#includecondition_variable#includefunctional#includethreadstructTimerTask{usingClockstd::chrono::steady_clock;Clock::time_point expire;std::functionvoid()cb;uint64_tid;booloperator(constTimerTasko)const{returnexpireo.expire;}// 小顶堆};classTimerHeap{public:uint64_tadd(std::chrono::milliseconds ms,std::functionvoid()cb){std::lock_guardstd::mutexlk(mtx_);TimerTask t{steady_clock::now()ms,std::move(cb),seq_};heap_.push(t);if(heap_.top().idt.id)cv_.notify_one();// 新任务更早到期唤醒returnt.id;}voidrun(){// 在独立线程调用while(true){std::unique_lockstd::mutexlk(mtx_);if(heap_.empty()){cv_.wait(lk);// 无任务则等}else{autotopheap_.top();cv_.wait_until(lk,top.expire);// 等至最近到期if(heap_.empty()||heap_.top().expiresteady_clock::now())continue;autotaskheap_.top();heap_.pop();lk.unlock();task.cb();// 执行回调锁外lk.lock();}}}std::priority_queueTimerTask,std::vectorTimerTask,std::greaterTimerTaskheap_;std::mutex mtx_;std::condition_variable cv_;uint64_tseq_0;};核心技巧cv_.wait_until(lk, top.expire)——当有人插入一个更早到期的任务时add里notify_one打断等待timer 线程重新计算最近到期避免新任务虽早却要等旧任务到点才触发的延迟 bug。这是定时器实现的关键正确性点。7. 定时器时间轮HashedWheelTimer当定时器数量极大十万级如海量连接心跳最小堆的O(log N)插入与每次 wakeup 都要扫堆顶会变慢。时间轮借鉴时钟一个环形数组槽指针按 tick 转动每 tick 推进一格执行该格所有任务。超时时间 一轮的用圈数round标记转到对应圈再执行。插入O(1)、删除O(1)适合大量短周期任务。Netty 的HashedWheelTimer即此思想。本篇给出概念骨架structWheelSlot{std::vectorTimerTasktasks;};std::vectorWheelSlotwheel_;// 如 512 槽size_t cursor_0;// tick(): cursor_ (cursor_1) % N; 执行 wheel_[cursor_] 中 round0 的任务// round0 的任务 round-- 并可能跨圈重挂面试对比堆定时器实现简单、精度高、适合少量定时任务时间轮插入删除 O(1)、适合海量定时但精度受 tick 粒度限制tick1ms 则误差1ms。8. 实战线程池 定时器 心跳模拟把两者结合线程池执行任务定时器每 3 秒打印一次心跳验证并发组件协作。#includeiostream#includechronointmain(){ThreadPoolpool(4);// 提交 10 个计算任务for(inti0;i10;i)pool.submit([i]{std::this_thread::sleep_for(std::chrono::milliseconds(100));std::couttask i done on std::this_thread::get_id()\n;});TimerHeap timer;std::threadtimer_thread([]{timer.run();});timer.add(std::chrono::seconds(3),[]{std::cout[heartbeat] alive\n;});timer.add(std::chrono::seconds(6),[]{std::cout[heartbeat] alive\n;});std::this_thread::sleep_for(std::chrono::seconds(7));// 真实项目里用原子 stop 标志优雅退出 timer 线程return0;}编译g -stdc17 pool.cpp -lpthread。你会看到 10 个 task 被 4 个 worker 复用执行定时器在 3s/6s 各触发一次。9. 与高性能服务器结合真实网络服务器如基于 epoll/io_uring通常用一个 accept 线程N 个 worker 线程每个跑一个事件循环即one loop per thread见 libevent/libev/muduo 思想。定时器集成进事件循环epoll 用timerfdio_uring 用IORING_OP_TIMEOUT而非独立线程——避免跨线程唤醒。计算密集任务才丢进独立线程池防止阻塞 I/O 事件循环。这是事件循环 线程池混合模型的典型架构面试常问为什么不能所有活都在事件循环线程做——答案长耗时任务会拖慢所有连接的事件处理必须卸载offload到线程池。10. 速答 12 题临场背诵线程池核心组成一组 worker 线程 任务队列 同步机制mutex/condvar 或无锁队列。为什么任务要在锁外执行防止持锁运行导致 worker 串行化最大化并发。条件变量为什么用 while 判断防虚假唤醒且 stop_ 也要能唤醒退出。submit 返回 future 怎么实现packaged_task包任务存shared_ptr进队列get_future()返回。packaged_task 为何要 shared_ptr它不可拷贝push 进std::function需共享所有权。任务抛异常会怎样有 future 版在 get() 重抛无返回值版会 terminate worker需 try/catch。CPU 密集 vs I/O 密集线程数前者≈核数后者可远大于核数靠压测定。最小堆定时器插入复杂度O(log N)取最近到期 O(1)。wait_until 的作用timer 线程等到最近到期新更早任务插入时 notify 打断重算。时间轮适用场景海量十万级定时任务插入删除 O(1)精度受 tick 限制。为什么长任务不能放事件循环线程会阻塞所有连接事件处理应 offload 到线程池。epoll 定时器怎么实现timerfd注册进 epoll超时即可读事件。11. 临场口诀池子复用线程队列削峰限并发任务锁外跑future 包结果堆定时器按点到时间轮海量快长活别占事件环卸载线程池才稳。12. 生产级增强方向基础版线程池能跑但离生产还差几步优雅停机drain 模式基础析构直接丢弃队列剩余任务。生产应提供shutdown(waittrue)置stop_后先处理完队列中已有任务再退出drain或shutdownNow立即丢弃。结合std::atomicbool而非裸bool避免数据竞争。工作窃取work-stealing单一全局队列在高并发提交时成为锁热点。更高阶做法是为每个 worker 配一个双端队列deque自己从头取、其他 worker 从尾部偷——std::deque 每线程独立 mutex或参照 Intel TBB /folly::MPMC实现。这把集中锁分散为局部锁 偶尔偷取吞吐更高。线程亲和性把 worker 绑到特定 CPUpthread_setaffinity_np减少跨核缓存失效配合 NUMA 把内存分配靠近线程所在节点。动态扩容固定线程数简单但 I/O 阻塞时可能不够。可设核心池 临时线程空闲超时回收类似CachedThreadPool但要防线程数爆炸——加上限与空闲回收。13. 线程池常见坑面试必考任务在锁内执行若task()在持mtx_时运行所有 worker 被串行化线程池退化为单线程。必须锁外执行见第 1 节。析构时任务抛异常无返回值版submit的task()若抛异常会std::terminate整个进程。生产须包try/catch或要求任务 noexcept。重复 join / 在 worker 内 submit 自身池在 worker 线程里向同一个池submit并future.get()会死锁线程被占用无人执行该任务。解决办法使用std::async(std::launch::async)或独立的继续continuation机制而非同池阻塞等待。stop_ 非原子用std::atomicbool stop_而非裸bool否则编译器优化可能让 worker 看不到更新。notify 遗漏向空队列 notify 无副作用但若submit在push前 notify 会丢唤醒。务必先push后notify。线程数大于任务数导致空转worker 全阻塞在cv_.wait无任务时仍占内存长时间空闲可考虑超时回收。14. 定时器取消与层级时间轮真实服务器常需要取消定时器如连接正常关闭不必再发心跳。最小堆取消需id - 堆内位置的额外映射如std::unordered_mapid, 堆索引 惰性删除标记。时间轮取消则是从对应槽移除节点O(1)更易实现。当定时跨度极大从毫秒到数小时单轮时间轮槽数爆炸改用层级时间轮hierarchical wheel类似时钟的秒针、分针、时针低精度轮溢出时把任务升级到高精度轮。Linux 内核timer wheel与 NettyHashedWheelTimer都基于此。面试答海量 长跨度定时时应主动提到层级时间轮体现深度。15. 与可观测性结合线程池与定时器是线上故障高发点任务堆积队列越来越长、某 worker 卡死线程长时间 100%、定时器泄漏不断 add 不 cancel。建议暴露指标pending_tasks队列长度、active_threads、completed_total。用 S03 的 perf /perf trace抓长时间运行的任务用gdb对卡死 worker 抓栈见 S09。定时器加上限监控防泄漏。把这些写完组件 能观测 能排查连起来正是 S01–S09 全系列想训练的工程闭环。16. 定时器融入事件循环timerfd epoll第 6、7 节的定时器用独立 timer 线程。但在 epoll 事件循环S01里更地道的是用timerfd创建一个定时器 fd把它EPOLL_CTL_ADD进 epoll超时后 epoll 报可读读一下即可触发到期任务。这样定时器与网络 I/O 共用一个事件循环无需跨线程唤醒inttfdtimerfd_create(CLOCK_MONOTONIC,0);structitimerspecits{};its.it_value{3,0};// 3 秒后首次its.it_interval{3,0};// 之后每 3 秒timerfd_settime(tfd,0,its,nullptr);epoll_ctl(epfd,EPOLL_CTL_ADD,tfd,ev);// 注册// 事件循环里tfd 可读 → read(tfd,...) 消耗通知 → 执行心跳这种一切皆 fd、统一进 epoll的思想和 io_uring 的IORING_OP_TIMEOUT异曲同工——都是把定时器变成事件源。面试若被问怎么在单线程事件循环里做定时答timerfdepoll 系或OP_TIMEOUTio_uring 系即可。17. 线程池 vs 协程C20C20 引入无栈协程co_await/task它和线程池解决不同层面的问题线程池解决并行执行多个独立任务、控制并发度任务间切换由 OS 调度开销是线程级。协程解决单个任务内部在 I/O 等待时让出不阻塞线程切换是用户态、开销极小适合海量连接各自顺序写逻辑的场景一个连接一个协程看起来像同步代码实则异步。现代框架如 cppcoro、asio 的 awaitable把协程跑在线程池的 worker 上线程池提供并行度协程提供异步不阻塞线程的写法。两者不是替代而是互补。面试答协程会不会取代线程池——答协程是任务内部挂起机制线程池是并行执行载体常结合使用体现体系化认知。18. 阻塞队列自测题附线程池的底层是线程安全的任务队列。常考手写一个阻塞队列templateclassTclassBlockingQueue{std::queueTq_;std::mutex m_;std::condition_variable cv_;booldone_false;public:voidpush(T v){std::lock_guardstd::mutexlk(m_);q_.push(std::move(v));cv_.notify_one();}boolpop(Tout){// 返回 false 表示已关闭std::unique_lockstd::mutexlk(m_);cv_.wait(lk,[this]{returndone_||!q_.empty();});if(q_.empty())returnfalse;// done_ 且空outstd::move(q_.front());q_.pop();returntrue;}voidclose(){std::lock_guardstd::mutexlk(m_);done_true;cv_.notify_all();}};这其实就是线程池任务队列的精简版掌握它线程池就通了。19. 速查并发组件决策表场景推荐方案理由少量定时心跳、超时最小堆定时器实现简单、精度高、O(logN) 可接受海量定时十万级连接时间轮 / 层级时间轮插入删除 O(1)tick 粒度控精度单线程事件循环里做定时timerfd epoll一切皆 fd统一事件源CPU 密集批量任务固定线程池核数个避免切换吃满算力I/O 密集任务线程池核数用等待时间换并发度长耗时任务怕阻塞 I/O卸载到独立线程池保护事件循环不被拖垮需要任务返回值submit 返回 futurepackaged_task 接异常与结果高频小回调、不存储function_ref零开销、非拥有、免分配这张决策表把前面所有点收敛成什么时候用什么。面试被问你怎么选定时方案/线程数时按表逐条给出权衡比背定义得分高得多。记住铁律事件循环只做 I/O 调度重活卸载线程池少量定时用堆、海量定时用轮热路径回调用 ref 而非 function。20. 临场自检三问并发组件“为什么任务要在锁外执行”—— 若持锁运行task()所有 worker 被串行化线程池退化成单线程锁只保护队列临界区越小并发越高。“定时器用堆还是轮”—— 少量定时用最小堆简单、O(logN)、精度高海量十万级用时间轮插入删除 O(1)精度受 tick 限制单线程事件循环用 timerfd 统一进 epoll。“长任务能放事件循环线程吗”—— 不能会阻塞所有连接事件处理必须卸载到线程池保护 I/O 调度不被拖垮。这三条是线程池与定时器面试的高频收口问题能倒背如流即过关。动手建议把第 1 节的线程池与第 8 节的定时器组合编译运行g -stdc17 -pthread故意提交一个会抛异常的任务观察 worker 是否被terminate再给 TimerHeap 插入一个比当前堆顶更早到期的任务验证wait_until是否被正确唤醒。踩过这些坑你讲出来的线程池才是有血有肉的工程经验而不是教科书定义。同时把这些组件与 S01 的 epoll、S05 的 io_uring 结合起来思考事件循环负责 I/O 调度线程池负责计算卸载定时器负责超时与心跳三者拼成一台完整的高并发服务器。记住线程池与定时器的价值不在能跑而在并发可控、任务可观测、停机可优雅——这三点是生产级组件与玩具的分界线。

相关新闻

计算机毕业设计之钢铁生产系统的设计与实现

计算机毕业设计之钢铁生产系统的设计与实现

随着网络科技的不断发展以及人们经济水平的逐步提高,网络技术如今已成为人们生活中不可缺少的一部分,而信息管理系统是通过计算机技术,针对用户需求开发与设计,该技术尤其在各行业领域发挥了巨大的作用,相比于以前的传…

2026/8/18 19:23:32 阅读更多 →
Python时间处理全解析:从time模块到datetime时区转换实战

Python时间处理全解析:从time模块到datetime时区转换实战

1. 项目概述:Python时间处理的基石 在任何一个涉及数据记录、任务调度、日志分析或者用户交互的Python项目中,时间处理都是一个绕不开的基础环节。无论是记录一条数据的创建时间,计算一个函数的执行耗时,还是将数据库里的一串数字…

2026/8/18 19:23:32 阅读更多 →
OpenRouter Ori Prime Agent 调用指南:从 API 集成到生产部署

OpenRouter Ori Prime Agent 调用指南:从 API 集成到生产部署

1. 先搞清楚 Ori Prime Agent 是什么,以及它和普通 API 调用有什么区别 OpenRouter 推出的 Ori Prime Agent,不是一个新模型,也不是一个独立软件。它本质上是一个 预配置的、可直接通过 API 调用的智能体服务 。你可以把它理解为一个“开箱…

2026/8/18 19:22:31 阅读更多 →

最新新闻

HTTP QUERY方法详解:复杂查询的标准化解决方案与Spring Boot实践

HTTP QUERY方法详解:复杂查询的标准化解决方案与Spring Boot实践

在 HTTP 协议的发展历程中,GET、POST、PUT、DELETE 等方法是开发者最熟悉的工具。然而,随着应用场景的复杂化,特别是对复杂查询和搜索需求的增长,传统的 GET 方法在语义和功能上开始显得力不从心。GET 方法虽然用于获取资源&#…

2026/8/18 19:55:47 阅读更多 →
DeepSeek Harness 小白入门 22:strict JSON Schema:结构更稳,但为什么仍要二次校验

DeepSeek Harness 小白入门 22:strict JSON Schema:结构更稳,但为什么仍要二次校验

DeepSeek Harness 小白入门 22:strict JSON Schema:结构更稳,但为什么仍要二次校验 [!NOTE] 这是 第二阶段 协议护栏 的第 22 课。本文面向第一次接触 Agent Harness 的读者,目标是:正确使用 strict 工具 Schema 并保留应用侧验证。真实练习场景是:让工具参数严格满足城…

2026/8/18 19:55:47 阅读更多 →
视频实时翻译神器:一键生成双语字幕,跨平台高效处理外语视频

视频实时翻译神器:一键生成双语字幕,跨平台高效处理外语视频

你是不是也遇到过这样的场景:好不容易找到一份宝贵的外语学习资料、技术讲座或者行业报告视频,结果发现没有字幕,或者字幕是外语的,看得一头雾水?手动翻译?效率太低。找在线工具?要么收费&#…

2026/8/18 19:55:47 阅读更多 →
DeepSeek Harness 小白入门 23:标准端点还是 /beta?带工具时千万别混用

DeepSeek Harness 小白入门 23:标准端点还是 /beta?带工具时千万别混用

DeepSeek Harness 小白入门 23:标准端点还是 /beta?带工具时千万别混用 [!NOTE] 这是 第二阶段 协议护栏 的第 23 课。本文面向第一次接触 Agent Harness 的读者,目标是:分清标准 Chat Completions 与 Beta 补全能力。真实练习场景是:为工具调用固定官方标准 Base URL。全…

2026/8/18 19:55:47 阅读更多 →
物业数智化落地的「红黑榜」技术解构:一份工单数据背后的系统差距

物业数智化落地的「红黑榜」技术解构:一份工单数据背后的系统差距

一、从一份评定结果看物业数智化的真实水位 2026年8月,尖草坪区物业服务企业第一批"红黑榜"如期出炉。这份评定依据是综合打分、投诉工单转办、平台受理数据和日常巡检记录——四项维度中,投诉工单转办和平台受理数据两项,直接反映…

2026/8/18 19:55:47 阅读更多 →
Weblogic+iframe解析问题

Weblogic+iframe解析问题

方法 A&#xff1a;在父页面加 <meta> 标签<head><meta http-equiv"Connection" content"close"> </head>⚠️ 这个 meta 标签会被浏览器忽略——HTTP/1.1 规范不允许用 meta 控制 Connection 头。方法 B&#xff1a;在父页面用 J…

2026/8/18 19:54:47 阅读更多 →

日新闻

告别逐帧截图:用 extract-video-ppt 快速提取视频中的 PPT 并一键导出 PDF

告别逐帧截图:用 extract-video-ppt 快速提取视频中的 PPT 并一键导出 PDF

告别逐帧截图&#xff1a;用 extract-video-ppt 快速提取视频中的 PPT 并一键导出 PDF 【免费下载链接】extract-video-ppt extract the ppt in the video 项目地址: https://gitcode.com/gh_mirrors/ex/extract-video-ppt 如果你还停留在"看网课 不停暂停 截图 …

2026/8/18 0:00:57 阅读更多 →
思源宋体TTF一站式上手:7个字重免费商用,从下载到上线的完整走查

思源宋体TTF一站式上手:7个字重免费商用,从下载到上线的完整走查

思源宋体TTF一站式上手&#xff1a;7个字重免费商用&#xff0c;从下载到上线的完整走查 【免费下载链接】source-han-serif-ttf Source Han Serif TTF 项目地址: https://gitcode.com/gh_mirrors/so/source-han-serif-ttf 你是不是也经历过这种时刻&#xff1a;设计稿里…

2026/8/18 0:00:58 阅读更多 →
华硕笔记本控制权回收指南:GHelper 如何用一个 10MB 文件替代 Armoury Crate

华硕笔记本控制权回收指南:GHelper 如何用一个 10MB 文件替代 Armoury Crate

华硕笔记本控制权回收指南&#xff1a;GHelper 如何用一个 10MB 文件替代 Armoury Crate 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, …

2026/8/18 0:00:59 阅读更多 →

周新闻

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

如果你是一名开发者&#xff0c;最近可能已经感受到了AI大模型正在从“玩具”变成“生产力工具”的强烈信号。从代码补全到智能Agent&#xff0c;从本地部署到云端API&#xff0c;我们正处在一个技术栈快速重构的节点。然而&#xff0c;面对层出不穷的模型、框架和工具&#xf…

2026/8/18 9:15:35 阅读更多 →
工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/18 9:06:28 阅读更多 →
【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。&#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室&#x1f447; 关注我领取海量matlab电子书和…

2026/8/18 9:04:56 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速&#xff1a;macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/17 18:54:37 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南&#xff1a;3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗&#xff1f;ncmdump解密工具帮你轻松解决这个困…

2026/8/17 18:55:16 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片&#xff1a;为英语学习 App 打造桌面级学习助手适用平台&#xff1a;HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0&#xff08;API 26 Beta&#xff09;新增了 AgentCard 智能体卡片能力&#xff0c;这是继 HMAF&#xff08;鸿蒙智能体框架&#x…

2026/8/17 18:55:55 阅读更多 →