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

异步任务调度器的核心设计与实现

任务并发控制

    • 为什么需要任务并发控制
    • 什么是任务并发控制
    • 核心设计
    • 拆解
      • 构造器部分
      • 设置阈值部分
      • 增加任务方法
      • 核心调度方法
    • 形象总结
    • 完整代码

为什么需要任务并发控制

  • 我们在面试里常会被问到:“如何控制并发请求数量?”
  • 有人答 Promise.all——那只能“一股脑”发出;
  • 有人答async/await循环——那只能“串行”排队。
  • 但是如果想“同时跑 N 个,其余排队,自然补位”,就得靠并发任务调度器

什么是任务并发控制

  • 并发任务调度器是一种运行时调度机制,它依据预设的并发度(pool size)对异步任务进行排队与准入控制:在任意时刻仅允许最多 N 个任务同时进入事件循环执行,超出部分按 FIFO(先进先出) 缓存在等待队列;每当运行中任务结束,调度器立即从队列头部取出新任务补位,从而在保证资源利用率最大化的同时,防止因瞬时高并发导致线程/连接/内存等资源耗尽。

核心设计

  1. 等待队列:等待队列是一个普通数组,按 FIFO 顺序缓存待执行的 { fn, resolve } 元组:新任务从尾部推进,调度器每次从头部弹出,既保证提交顺序,又通过简单的 shift/push 实现 O(1) 级入队与出队。
  2. 计数器:runningTaskCount 计数器实时记录当前已占用的并发槽位数,每次任务启动前自增、任务结束后自减,成为调度循环唯一的“信号灯”,确保任意时刻运行任务量不超过预设阈值。
  3. 调度循环:runTask() 采用“贪婪填充”策略:在 while 循环中持续检测槽位未满 && 队列有任务,立即弹出并启动新任务;任务完成回调里再次递归调用自身,从而把可用并发额度一次性填满,实现零延迟补位。
  4. 动态扩容:setPoolSize(newSize) 允许运行期任意修改并发上限,调整后会立即触发一次 runTask(),若新上限大于当前占用数,等待队列中的任务将被即时拉取执行,无需重启调度器即可在线扩/缩容。

拆解

构造器部分

  • 初始化数组、设置阈值、初始化计数器
 constructor({poolSize}) {this.waiting = [];this.poolSize = poolSize || 2;this.runningTaskCount = 0;}

设置阈值部分

  • 可以根据这个方法动态设置PoolSize
    setPoolSize(size){this.poolSize = size;this.runTask();}

增加任务方法

  • 提交任务接口,返回 Promise 以便外部等待
    add(fn){return new Promise((resolve)=>{this.waiting.push({fn,resolve});this.runTask();})}

核心调度方法

  • 使用finally来处理:任务无论成功还是失败都要计数器-1
  • 递归检查是否还能继续处理任务
 runTask() {while (this.runningTaskCount < this.poolSize &&this.waiting.length) {const { fn, resolve } = this.waiting.shift();this.runningTaskCount++;fn().finally(() => {      // 任务无论成功失败都要减计数this.runningTaskCount--;this.runTask();         // 递归检查是否还能继续填空resolve();              // 通知外部“我跑完了”});}}

形象总结

  • 并发调度器就像一个异步红绿灯,**绿灯数(阈值)**固定,车多就排队,车走自动补位,让整条街吞吐最大又永不堵死。

完整代码

class SuperTask {constructor({poolSize}) {this.waiting = [];this.poolSize = poolSize || 2;this.runningTaskCount = 0;}setPoolSize(size){this.poolSize = size;this.runTask();}add(fn){return new Promise((resolve)=>{this.waiting.push({fn,resolve});this.runTask();})}runTask(){while(this.runningTaskCount < this.poolSize && this.waiting.length > 0){const {fn,resolve} = this.waiting.shift();this.runningTaskCount++;fn().then(()=>{resolve();this.runningTaskCount--;this.runTask();})}}
}
http://www.dtcms.com/a/618597.html

相关文章:

  • 上海市建设工程合同备案网站网站托管一般多少钱
  • 网站建设方案如何写营销培训生
  • [智能体设计模式] 第15章:智能体间通信(A2A)
  • 网页图片怎么保存为pdf文件网站优化及推广公司
  • 云脑网络科技网站建设wordpress 中文 模板
  • pycharm怎么将背景换成白色
  • 具身智能:研究现状深度解析——从技术突破到产业落地
  • 网站建设台州网站备案密码格式
  • 多路转接select(2)
  • 电子行业安规测试中常见术语及含义
  • 深度学习中的正交化:理论、应用与实现
  • 18+网站推广检察院门户网站建设情况总结
  • 柯尼卡美能达C7222色彩调整及更换硒鼓注意事项
  • 4K60矩阵:开启超高清无缝拼接新时代
  • 教务处网站建设方案软文营销案例200字
  • 如何在Linux中找到MySQL的安装目录
  • Ansible变量全解析:优化自动化流程的关键
  • Leetcode 3747. Count Distinct Integers After Removing Zeros
  • 西安网络建站公司考研培训班哪个机构比较好
  • 第二部分:感知篇——汽车的“眼睛”与“耳朵”(第3章:传感器技术深度解析)
  • 深度解析类和对象(2)
  • 青浦网络公司网站wordpress快速插图
  • 河南城乡与住房建设厅网站网站推广怎么样
  • 基于51单片机的DHT22温湿度检测调节系统
  • 闵行网站制作公司水泵网站站群建设
  • 【昇腾】基于Atlas 200I DK A2开发者套件跑sampleYOLOV7 demo解决有些图片不识别不画框的问题_20251116
  • 【科技素养】蓝桥杯STEMA 科技素养组模拟练习试卷 6
  • 网站可信认证在哪里做如何开一个网站
  • 20.传输层协议TCP
  • Flink Oracle CDC Connector 实战指南