多级反馈队列调度器:原理、边界与调参实战
1. 我为什么把调度器从“单队列”改成“多级反馈队列”1.1 先来先服务和时间片轮转的账都算不平多级反馈队列这名字听起来像操作系统教材里一个遥远的概念但真到自己动手写调度器的时候你会发现它其实是“妥协”两个字最典型的代表。我最早维护的一个教学用模拟内核调度器选型特别朴素一开始用先来先服务写起来倒是简单维护一个就绪队列谁先到谁先跑。但跑交互型负载的时候问题马上出来了。假设有三个进程第一个进程是 CPU 密集型的需要连续计算 100 个时间单位另外两个进程是交互型的每隔 4 个时间单位就唤醒一次需要立即得到响应。先来先服务会把 CPU 密集型进程从头到尾跑完另外两个进程的平均响应时间直接变成上百时间单位。用户体感就是“点了按钮半天没反应”。那就换时间片轮转吧。轮到每个进程给一个固定时间片比如 1 个时间单位跑完就切换。交互型进程的响应时间一下子就降下来了但新问题也来了CPU 密集型进程本来一次能算一整块现在每 1 个时间单位就被打断一次频繁的上下文切换让系统开销肉眼可见地涨。我在模拟环境里统计过当进程数量从 3 个涨到 30 个仅切换开销一项就占了总 CPU 时间的接近 15%。更关键的是轮转调度对 I/O 密集型的进程其实并不友好——它们在时间片内往往只用了 1 毫秒 CPU 就去等 I/O 了剩下的时间片被白白浪费等 I/O 回来又要重新排队白白多等一轮。如果提前知道每个进程的特征理论上可以做到完美调度短任务优先长任务后置。但现实里你永远不会提前知道一个进程接下来是打算长时间计算还是马上要读磁盘。所以需要一个自适应方案调度器先不假设进程是什么类型而是通过观察它的行为动态调整优先级。这就是多级反馈队列的出发点。1.2 MLFQ 的核心思路让调度器“见人下菜碟”多级反馈队列的设计哲学可以概括成一句话历史行为是预测未来行为的最好指标。如果一个进程总是把时间片用完才让出 CPU说明它极可能是 CPU 密集型的那么调度器就逐渐降低它的优先级如果一个进程总是用一小会儿 CPU 就让出说明它可能是在等待 I/O调度器就一直把它留在高优先级队列里让它每次唤醒都能快速拿到 CPU。这套思路放到生活里也很好理解。一个餐厅服务员如果看到某桌客人每次上菜后 5 分钟就叫服务员肯定默认这桌客人需求多会下意识关注这桌如果某桌客人一晚上都不怎么叫人服务员就会把注意力放到别处。多级反馈队列做的就是这件事根据进程过去一段时间的行为动态调整它未来的“被关注程度”。我当时选择重写调度器还有一个原因是多级反馈队列不要求提前知道进程特征也不需要用户手动调整优先级。它把所有进程统一对待靠规则自己区分出长短任务、交互任务和后台计算任务。这种自适应能力对于一个负载类型没法预判的通用内核来说实在是太重要了。2. MLFQ 的调度规则拆解四规则和两个极易踩的边界2.1 四个调度规则的精确定义多级反馈队列的完整实现有很多变体但核心规则可以归纳为以下四条规则一新任务进入最高优先级的队列。不管它是一个刚启动的编辑器还是一个马上要跑一小时的编译任务一律先放进最顶层队列 Q0。原因很简单调度器还不知道它是什么类型先给它最高优先级试探一下看它怎么用这个时间片。规则二任务在当前队列中按时间片轮转。同一层队列内部的多个进程按照先来先服务加时间片轮转的方式共享 CPU。Q0 的时间片最短越往下的队列时间片越长。规则三如果任务在时间片结束前主动让出 CPU比如等待 I/O它留在当前队列如果任务用完了整个时间片才让出 CPU它降级到下一级队列。这是整个算法最核心的一条。前者说明任务很可能需要快速响应后者说明任务大概率是 CPU 密集型可以让它去下面慢慢跑。规则四每隔固定周期 S把所有任务一次性提升到最高优先级队列。这条规则是为了防止低优先级队列里的任务永远得不到 CPU。先别急着背规则我建议你在实现的时候把规则三想透彻。它是整个 MLFQ 的行为分水岭让出 CPU 的时机直接决定了任务被判定成“交互型”还是“计算型”。我当初第一次实现时犯过一个典型错误只要任务在时间片内让出 CPU都留在当前队列但我没有区分“任务主动让出”和“任务被抢占”结果高优先级队列里堆积了大量被抢占后重新入队的任务低优先级队列反而越来越空整个调度的区分度被抹掉了。这种细节在课本的伪代码里很难看出来但真实跑负载时差别非常明显。2.2 边界一饥饿问题与周期性提升没有规则四的多级反馈队列是非常危险的。设想一个极端场景系统里的 CPU 密集型任务特别多它们不断从高层降到底层新任务又源源不断地进入最高层队列。底层的某个老任务可能永远等不到执行机会。这在真实系统里叫饥饿和死锁不一样死锁是大家都不动饥饿是低优先级的进程一直看着别人跑。周期性提升就是解决饥饿的标准手段。把 S 设得太短比如 5 毫秒提升一次就会把已经降下去的 CPU 密集型进程频繁拽回顶层MLFQ 好不容易学出来的“行为分类”被完全打乱低层队列形同虚设把 S 设得太长比如 10 秒低优先级进程可能在被提升之前就已经等待得让用户无法忍受了。一般实现里S 的取值通常落在 50 毫秒到 1 秒之间具体要看时间片粒度和对响应时间的要求。这里还有个容易被忽略的细节提升操作本身也要消耗 CPU 时间。如果系统里有几千个进程每次提升都要遍历所有进程、修改它们的队列指针、重置时间片计数器这同样需要时间。所以提升周期不是拍脑袋定的需要结合进程数量和切换开销一起考虑。我在模拟内核里把 S 从 50 毫秒改成 500 毫秒后平均响应时间只增加了不到 8%但低层队列的吞吐量明显提升了。你不可能既让所有进程都秒回又不付出调度代价。2.3 边界二游戏系统与可预测性的危害多级反馈队列还有一个特别反直觉的问题被操作系统领域的文献称为“游戏系统”。我给你描述一个场景一个任务知道规则之后会在时间片只用了 90% 的时候主动让出 CPU。按照规则三它留在当前高优先级队列下一次调度又马上被选中。结果就是这个任务实际上获得了远超它应得比例的 CPU 时间而且其他任务很难发现它在作弊。我在自己项目里第一次遇到这种情况的时候以为是调度器出了 bug某个进程的 CPU 占用率统计接近 95%但按我的规则它一直留在最高优先级队列里。仔细排查后才发现是它的代码里有一个频繁的小 sleep恰好把每次 CPU 使用卡在时间片边缘。解决这个问题的通用思路是加入累计运行时间记账。也就是说与其严格看“本次时间片用完没有”不如看“这个任务在一段周期内累计使用了多少 CPU 时间”。如果累计时间远超同层其他任务即使它每次都主动让出也可能被强制降级。我在实现里给每个进程增加了一个total_runtime_in_this_level字段每次让它进该层队列时清零一旦累计运行时间超过了该层时间片的若干倍就立刻降级不管它让出的时机如何。这个补丁看着不起眼但它是让 MLFQ 保证公平性的一块重要基石。3. 用 Python 手写一个可观察的 MLFQ 模拟器3.1 进程模型与数据结构设计讲再多理论不如亲手实现一个最小可用的模拟器。我建议用 Python 写不是因为 Python 适合做内核而是因为模拟器需要的是快速迭代和直观观察Python 的 list 和 dict 足够清晰。进程模型我做了这样的简化每个进程由交替的 CPU 突发和 I/O 突发组成CPU 突发表示进程需要连续计算多少个时间单位I/O 突发表示进程会阻塞多久。这种交替模型虽然简单但足以模拟出交互型、混合型和 CPU 密集型的差异。数据结构上我用了三个核心对象Proc记录进程 ID、到达时间、当前 CPU 突发长度、当前 I/O 突发长度、当前所在队列层级、剩余时间片等。MLFQ维护一个队列数组self.queuesqueues[0]是最优先级队列越往后优先级越低。Clock一个全局计时器每递增一次代表一个时间单位。这里有个设计取舍要说明真实内核中进程就绪队列通常用链表实现因为你需要在队头做调度选择、在队尾加入新到达或 I/O 完成的进程。Python 里我直接用了collections.deque因为它的头尾操作都是 O(1)。你如果手写 C 版本绝不要用数组当循环队列然后频繁移动元素那会白白浪费调度开销。3.2 核心调度循环的实现调度循环的思路是这样的每个时间单位开始时从最高优先级队列往下找找到第一个非空队列取出队头进程作为当前运行进程让它运行一个单位然后根据规则更新它的状态。下面是简化版的伪代码我尽量保留了关键逻辑import collections from dataclasses import dataclass dataclass class Proc: pid: int cpu_burst: list # 每个元素的长度表示一次CPU突发用多少个时间单位 io_burst: list # 对应每个CPU突发后的IO时间 level: int 0 remain_slice: int 0 class MLFQ: def __init__(self, time_slices(1, 2, 4), boost_interval30): self.q [collections.deque() for _ in range(len(time_slices))] self.time_slices time_slices self.boost_interval boost_interval self.tick 0 def enqueue(self, p, level): p.level level p.remain_slice self.time_slices[level] self.q[level].append(p) def boost(self): 把所有进程移到最高优先级队列 for level in range(1, len(self.q)): while self.q[level]: p self.q[level].popleft() self.enqueue(p, 0) def schedule_next(self): for level in range(len(self.q)): if self.q[level]: return self.q[level].popleft() return None实际调度函数里我跑一次单位时间def run_one_unit(m, proc): # 运行一个单位后该进程剩余CPU突发时间减一 proc.cpu_burst[0] - 1 proc.remain_slice - 1 if proc.cpu_burst[0] 0: # CPU突发结束说明进程主动让出或去等I/O io proc.io_burst[0] if io 0: # 模拟I/O阻塞这里简化为直接跳过io个时间单位 m.tick io proc.cpu_burst.pop(0) proc.io_burst.pop(0) # 留在当前层 m.enqueue(proc, proc.level) elif proc.remain_slice 0: # 时间片用完但CPU突发还没完降级 next_level min(proc.level 1, len(m.time_slices) - 1) m.enqueue(proc, next_level) else: # 时间片没完CPU突发也没完继续运行 return proc return None注意我在代码里做了两个简化第一I/O 阻塞时间直接用m.tick io跳过这在模拟器里是可以接受的但如果要统计“响应时间”就要谨慎因为跳过 I/O 期间其他进程其实还在运行第二我没有考虑进程到达时间的交错真实内核中到达事件由时钟中断触发模拟器里可以假设所有进程一开始全部就绪或者用一个事件队列来管理到达。这两种做法取决于你想观察什么。3.3 三种典型进程的模拟结果分析我给模拟器造了三个进程特征故意拉开差距进程CPU 突发模式I/O 突发模式类型判定A每次 1 单位每次 7 单位交互型B每次 4 单位每次 3 单位混合型C每次 24 单位每次 2 单位CPU 密集型三进程同时到达时间片序列设为(1, 2, 4)提升周期设为 30 个时间单位。跑完一轮总计时长约 80 个时间单位的模拟结果让我印象深刻进程 A 绝大多数时间待在 Q0几乎每次从 I/O 唤醒后都能在一个时间单位内被调度进程 B 在 Q0 和 Q1 之间浮动偶尔落到 Q2进程 C 很快从 Q0 降到 Q1再降到 Q2一直在 Q2 用 4 个时间单位的长时间片慢慢跑。由此可见MLFQ 很自然的做到了将 I/O 密集任务提升到高优先级并将 CPU 密集任务的优先级压低。不需要任务自我声明也不需要管理员手动配置这就是它的自适应性。不过这个效果有一个前提时间片必须短到能捕捉到进程的行为特征。如果我把 Q0 的时间片从 1 改成 20进程 C 在 Q0 里就能跑一大半 CPU 突发降级动作会变得迟钝交互型进程 A 的响应时间也会被拉长。后面我会专门讲时间片怎么配。4. 调参实战时间片、队列数、提升周期该怎么配合4.1 时间片序列的设计逻辑指数增长与固定比例MLFQ 里最容易被低估的参数是每层队列的时间片序列。常见做法有两种指数增长序列和固定比例序列。指数增长是最经典的比如(1, 2, 4, 8, 16)。数学上的好处是即使层数很深总等待时间也收敛得较快。假设一个进程从 Q0 一路降到 Q4它在每层最多等待的时间之和大致是(1 2 4 8 16) * 同层进程数这个数列是有上界的不会因为层数增加导致最底层的等待时间爆炸。这个性质对饥饿问题的控制很有帮助。固定比例序列比如(1, 10, 100)更极端底层任务一旦被降下去可能要等很久才能再拿到 CPU。它适合那种系统里基本都是交互任务、后台计算任务非常少的场景。我在模拟内核里做过对比实验指数序列下CPU 密集进程的平均完成时间比固定比例序列少了将近 40%同时交互型进程的响应时间没有明显变差。原因很简单底层进程虽然优先级低但时间片变长以后它每次拿到的 CPU 时间足够完成更多工作反而减少了被频繁打断的次数。选择时间片时还要考虑上下文切换开销。如果一次切换需要 0.05 个时间单位真实内核通常切换开销在微秒级到几十微秒级而 Q0 时间片只有 0.1 个时间单位那么切换开销会占到 CPU 时间的 30% 以上调度器大部分时间都在做无用功。所以时间片不能一味求短至少要大于切换开销的两个数量级。4.2 提升周期多久合适饥饿与吞吐之间的权衡提升周期 S 的取值我建议直接在模拟器里做扫描实验。拿上面的三进程负载分别把 S 设为 10、30、80观察两个指标交互进程的最大响应时间以及 CPU 密集进程的完成时间。我当时的实验数据大致如下提升周期 S交互进程平均响应CPU 密集进程完成时间低层队列被饿时间102.182几乎无303.476很短806.871偶尔出现等待超20这个表格揭示了一个很现实的权衡S 越短交互响应越好但 CPU 密集进程的完成时间变长了因为它的“学习成果”会不断被打断S 越长低层进程处理效率越高但交互进程的响应时间波动变大极端情况下会出现饥饿。没有一个“万能最佳值”只能根据你到底更在意响应时间还是更在意吞吐量来做取舍。我自己的经验是如果系统是桌面交互环境S 取 50 毫秒左右很舒服如果是在模拟内核里做批处理实验S 直接取 500 毫秒甚至不提升都可以。4.3 优先级反转一个容易被忽略的连锁问题调参调多了你以为把 MLFQ 的时间和层数配好就完了其实还有一个坑藏在共享资源的同步逻辑里优先级反转。场景是这样的低优先级进程 L 拿到了一个互斥锁正在临界区里写数据高优先级进程 H 也想要这把锁于是被阻塞这时候中优先级进程 M 开始疯狂占用 CPU因为调度器看到 M 比 L 优先级高就把 CPU 分给 ML 永远无法执行、也就无法释放锁结果是最高优先级的 H 被 M 和 L 一起“饿死”。这是真实系统中出现过的问题不是理论假设。解决优先级反转的标准做法是优先级继承当高优先级进程因为低优先级进程持有的锁而阻塞时低优先级进程临时把优先级提升到高优先级进程那一层。这相当于调度器识别出了“L 正在为 H 工作”于是给 L 开绿色通道。我在模拟器里给 Mutex 对象增加了一个inherited_level字段只有真正持有锁且阻塞了高优先级任务时才会激活等锁释放后再恢复原来的层级。这个机制和 MLFQ 的原有规则没有冲突但你必须显式处理否则调参调得再好锁竞争一多系统照样跳动。5. 从实验走向真实系统MLFQ 的变体和现代调度器里的影子5.1 教学内核里的 MLFQ 改造过程我后来把模拟器里的 MLFQ 移植进一个教学操作系统内核过程比想象中要复杂。模拟器里默认所有进程都是普通就绪态真实内核里还要处理睡眠态、等待态、被信号打断、多核负载均衡等情况。我遇到的第一个问题就是时钟中断与调度点的关系。模拟器里我可以按单位时间精确打断进程真实内核里必须依赖硬件定时器。我配置了一个 100Hz 的周期性时钟中断每个中断到来时会检查当前进程的时间片是否耗尽如果耗尽了就触发调度。但进程如果在时间片内调用了睡眠函数内核会立刻把当前进程挂起并重新调度而不是等中断来这里就需要额外维护一个“睡眠进程队列”唤醒后才能进入顶层的 MLFQ 就绪队列。第二个问题是多核环境下的队列竞争。单核版本只需要在关中断状态下操作队列多核版本如果还用一个全局队列数组就会遇到多个 CPU 同时取任务的竞争问题。我最后采用了“每 CPU 一个 MLFQ 实例 定期迁移”的方案虽然引入了负载均衡的复杂度但至少避免了锁竞争带来的调度延迟。如果你只是做作业或者复现实验单核足矣不要一上来就铺多核的摊子。5.2 商用时怎么补充公平性、CPU 亲和和功耗机制纯 MLFQ 在现代商业系统里很少单独出现因为它的公平性粒度太粗。现代操作系统通常会把 MLFQ 的“多层优先级”思想扩展成几十个优先级队列并在上面叠加各种策略实时任务放在最高优先级层普通线程按照交互性动态调整到不同层后台任务还有单独的节能队列。我见过一个很有意思的做法是把 MLFQ 和 CPU 亲和性结合每个进程刚创建时放在当前 CPU 的顶层队列只有在该 CPU 负载过高时才会把进程迁移到其他 CPU 的队列。这样做可以减少缓存失效因为进程尽量不换 CPU 跑。另外在功耗敏感的设备上调度器会降低长队列底部进程的频率而不是把 CPU 时间片分给它这也是对传统 MLFQ 思路的重要扩展。所以我的建议是不要把 MLFQ 当成一个“照着实现就完事”的算法而是要把它当成一个用反馈机制做行为分类的调度框架。理解了这一点你就能看懂现代调度器里各种复杂策略的来龙去脉也才能在需要的时候自己动手改造一版适合场景的调度器。6. 我自己踩过的坑和最后想说的几句话最后分享三个实际踩过的坑每一个都花了我不少时间排查。第一个是提升周期设得太短导致“失忆”。我一开始把提升周期设成 5 个时间单位想着“反正提升能让交互进程快速获得响应”结果所有进程都在顶层轮转MLFQ 变成了时间片轮转调度器CPU 密集型进程的吞吐量反而不如普通轮转。后来我把提升周期调大了 20 倍才恢复正常。调参之前一定要先想清楚这个参数在这个系统里到底在保护谁。第二个是忘记时间片边界“卡点”导致的不公平。我在实现规则三时只判断了“剩余时间片是否为 0”没有考虑“进程主动让出时是否已消耗大量时间片”。这就给了前面说的游戏系统钻空子的机会。补上累计运行时间统计之后问题才真正解决。第三个是低估了上下文切换开销。我在模拟器里把时间片设成 1 个单位跑得很欢移植到真实内核后1 毫秒时间片直接让系统 40% 的 CPU 时间花在保存和恢复寄存器、刷新 TLB 上。换成 4-8 毫秒之后才稳定下来。模拟器里的“单位时间”没有物理意义真实系统里一定要看切换成本。多级反馈队列是一个“看着简单、用着有门道”的调度算法。它解决的核心问题是我在开头说的那些响应时间与吞吐量的矛盾、交互任务与计算任务的区分、优先级动态调整的安全性。如果你准备自己实现一遍我希望你被我绕开的那几个坑去绕。先从单核模拟器跑起来再加上饥饿保护和记账机制最后再考虑真实内核里的中断、加锁和多核情况。每一步的取舍你都值得亲手算一遍账。

相关新闻

Java常用类编程实践与性能优化指南

Java常用类编程实践与性能优化指南

1. 项目概述作为一名Java开发者,我经常需要处理各种基础但重要的编程任务。最近在整理教学资料时,发现学生们对Java常用类的掌握程度参差不齐,特别是从第8题到第15题这些编程练习,涉及了String、Math、Date等多个核心类的使用。这…

2026/10/14 13:04:04 阅读更多 →
Excel夹:鸿蒙上原生读写xlsx表格工具

Excel夹:鸿蒙上原生读写xlsx表格工具

需要在鸿蒙手机上改Excel表?Excel夹原生支持xlsx读写,公式函数图表全支持,还能导出PDF。文件本地处理不上云,目前免费。#鸿蒙 #纯血鸿蒙 #鸿蒙next #Excel #办公

2026/10/14 13:04:04 阅读更多 →
pgAdmin 4 左侧图标空白?一条注册表命令快速修复

pgAdmin 4 左侧图标空白?一条注册表命令快速修复

问题现象 在使用 pgAdmin 4 客户端程序时,左侧面板中节点图标一直显示空白,如下图所示:问题原因 pgAdmin 4 左侧树形节点依赖 .svg 格式图标,当 Windows 系统中 .svg 文件的 MIME 类型映射缺失或错误时,客户端无法正确…

2026/10/14 13:03:03 阅读更多 →

最新新闻

整车八自由度Simulink动力学模型搭建:从方程到仿真验证

整车八自由度Simulink动力学模型搭建:从方程到仿真验证

做整车动力学仿真的人,几乎都会经历从二自由度自行车模型起步,再逐步往多自由度模型走的过程。二自由度模型能把横摆和侧向运动的基本逻辑讲清楚,但一涉及到载荷转移、侧倾对轮荷分布的影响、四个车轮独立的转速动力学,它就完全不…

2026/10/14 13:48:57 阅读更多 →
IMX6ULL嵌入式Linux文件系统目录操作指南

IMX6ULL嵌入式Linux文件系统目录操作指南

1. 项目概述作为一名嵌入式Linux开发者,我最近开始深入研究IMX6ULL这款性价比极高的ARM Cortex-A7开发板。在嵌入式Linux开发中,文件系统目录结构的理解和常用目录操作命令的掌握是基础中的基础。这篇文章将分享我在IMX6ULL开发板上学习Linux文件目录结构…

2026/10/14 13:48:57 阅读更多 →
快慢指针原理与实战:链表中间节点、环检测与入口定位

快慢指针原理与实战:链表中间节点、环检测与入口定位

1. 为什么快慢指针是链表问题的“万能钥匙”?——从三个经典问题看算法设计的本质快慢指针不是什么高深莫测的黑科技,它本质上是一种空间换时间的朴素思想在链表结构上的极致应用。我带过不少刚学数据结构的学生,他们第一次看到“用两个指针一…

2026/10/14 13:48:57 阅读更多 →
Workbench齿轮动力学仿真与工程优化实践

Workbench齿轮动力学仿真与工程优化实践

1. 项目概述:齿轮仿真的工程价值齿轮传动作为机械工业的"细胞",其动态特性直接影响着整个传动系统的可靠性、噪声水平和寿命。传统设计方法依赖经验公式和静态计算,难以捕捉高速运转下的真实行为。Workbench平台提供的齿轮动力学仿…

2026/10/14 13:48:57 阅读更多 →
C# OPC客户端调试:DA与UA双协议连接、读取、订阅全链路诊断

C# OPC客户端调试:DA与UA双协议连接、读取、订阅全链路诊断

简介:本资源是一个面向工业自动化与.NET开发者的C# OPC客户端实战项目,聚焦于使用OPC Net Api Chs库实现与OPC服务器的连接、数据读写、事件订阅及异常处理等核心通信功能,适用于具备基础C#和WinForm开发能力的中高级工程师学习工业协议集成。…

2026/10/14 13:48:57 阅读更多 →
ponytail:一个轻量原生JS前端插件,轻松搞定H5底部导航与运营浮层

ponytail:一个轻量原生JS前端插件,轻松搞定H5底部导航与运营浮层

ponytail 这个名字,好多人第一次听到都以为是来聊发型的。其实它是我很早就为了处理移动端 H5 底部导航和运营浮层写的一个微型前端插件,核心干的事情就一件:在页面任意指定位置追加一块内容,同时把动画、状态记忆、批量挂载这些看…

2026/10/14 13:47:56 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →