字节面试题:实现任务调度器(Scheduler)

突然想起去年面试字节时的一道题,题面大概是这样:

  1. 实现一个任务调度器 scheduler
  2. 只能同时执行 n 个任务
  3. 当有 n 个任务正在执行时,后安排的任务要排队

当时很久没面试了,紧张到冒汗😓,只写出一半就被叫停了;

今天辗转反侧睡不着,突然想起这道题,就给他写了吧 :)

实现

大致思路是:

  1. 定义 Scheduler 类:指定同时执行的任务数 n
  2. schedule 方法:安排一个任务(task),如果执行中的达到 n 则入队,否则直接执行
  3. 包装器 wrapper包装 task,使执行 task 完毕后检查是否要出队,即执行新任务

伪码如下:

typescript 复制代码
class Scheduler {
  // 计数当前执行中的数量
  private runningTask: number
  // 最大并发
  private capacity: number
  // 等待队列
  private pendingQueue: (() => Promise<any>)[]

  constructor(capacity: number) {
    this.capacity = capacity
    this.runningTask = 0
    this.pendingQueue = []
  }

  private wrapTask<T>(task: () => Promise<T>): () => Promise<void> {
    return async () => {
      // 执行 task
      // 判断 pending 队列是否空
      // 否,出队下一个 task
      // 是,更新计数
    }
  }

  public schedule<T>(task: () => Promise<T>): void {
    // 包装 task,得到 wrappedTask
    // 判断计数是否达到 n
    // 否,则直接执行 wrappedTask
    // 是,则入队
  }
}

然后,让我们来实现它:

typescript 复制代码
class Scheduler {
  // 计数当前执行中的数量
  private runningTask: number
  // 最大并发
  private capacity: number
  // 等待队列
  private pendingQueue: (() => Promise<any>)[]

  constructor(capacity: number) {
    this.capacity = capacity
    this.runningTask = 0
    this.pendingQueue = []
  }

  private wrapTask<T>(task: () => Promise<T>): () => Promise<void> {
    return async () => {
      // 执行 task
      await task()
      // 判断 pending 队列是否空
      if (this.pendingQueue.length > 0) {
        // 否,出队下一个 task
        const nextWrappedTask = this.pendingQueue.shift()!
        nextWrappedTask()
      } else {
        // 是,更新计数
        this.runningTask--
      }
    }
  }

  public schedule<T>(task: () => Promise<T>): void {
    // 包装 task,得到 wrappedTask
    const wrappedTask = this.wrapTask(task)
    // 判断计数是否达到 n
    if (this.runningTask < this.capacity) {
      // 否,则直接执行 wrappedTask
      wrappedTask()
    } else {
      // 是,则入队
      this.pendingQueue.push(wrappedTask)
    }
  }
}

进阶

这里还可以进一步:要求 schedule 返回 Task 的执行结果,怎么写?

EZ,我们只要:schedule 返回一个 Promise,并在 wrappedTaskresolve 结果 就行了,代码如下:

PS: 这里总结一个小技巧"传递 resolve/reject 来实现异步返回值"

typescript 复制代码
class Scheduler {
  private runningTask: number
  private capacity: number
  private pendingQueue: (() => Promise<any>)[]

  constructor(capacity: number) {
    this.capacity = capacity
    this.runningTask = 0
    this.pendingQueue = []
  }

  private wrapTask<T>(task: () => Promise<T>, resolve: (value: T) => void, reject: (error: any) => void): () => Promise<void> {
    return async () => {
      try {
        const res = await task()
        resolve(res)
        const nextTask = this.pendingQueue.shift()
        if (nextTask) {
          nextTask()
        } else {
          this.runningTask--
        }
      } catch (e) {
        reject(e)
      }
    }
  }

  public async schedule<T>(task: () => Promise<T>): Promise<T> {
    return (new Promise<T>((resolve, reject) => {
      const wrappedTask = this.wrapTask(task, resolve, reject)
      if (this.runningTask < this.capacity) {
        this.runningTask++
        wrappedTask()
      } else {
        this.pendingQueue.push(wrappedTask)
      }
    }))
  }
}
相关推荐
掰头战士8 小时前
多重影分身!恨不得把一个agent掰成两个? 还真能干!
typescript·llm·agent
Sam_Deep_Thinking8 小时前
new Thread()之后发生了什么?
java·后端·面试·程序员
用户938515635079 小时前
从小米前端面试题,彻底搞懂闭包、作用域链与 useState 惰性初始化
前端·面试
怕浪猫10 小时前
从 Windows 换到 Mac 三个月,我真香了
算法·面试·架构
shmily麻瓜小菜鸡12 小时前
TDD(测试驱动开发)详解
开发语言·javascript·typescript·node.js·ecmascript
古希腊掌管代码的神THU12 小时前
【清华代码熊】DeepSeek-V4.1-Flash 多模态架构解析
人工智能·深度学习·机器学习·自然语言处理·面试
林川~0116 小时前
Unity 反射(Reflection)从原理到实战:一篇讲透原理、用法、实战案例与性能优化
面试·性能优化·反射·il2cpp·type
晚安日记wanna16 小时前
React 为何不做双端 diff?Vue 与 React 更新逻辑的三层差异
前端·react.js·面试
keke.shengfengpolang17 小时前
2026年资金分析岗校招技术栈拆解:Excel预测模型、SQL取数、SAP与Oracle资金模块,附2027届备考路线
面试
顶点多余17 小时前
9.16 面试总结
linux·面试·职场和发展