前端面试题:实现一个带并发限制的异步调度器 Scheduler

        题目:实现一个带并发限制的异步调度器 Scheduler,保证同时运行的任务最多有N个。完善下面代码中的 Scheduler 类,使得以下程序能正确输出:

class Scheduler {
  add(promiseCreator) { ... }
  // ...
}

const timeout = (time) => new Promise(resolve => {
  setTimeout(resolve, time)
})

const scheduler = new Scheduler(n)
const addTask = (time, order) => {
  scheduler.add(() => timeout(time)).then(() => console.log(order))
}

addTask(1000, '1')
addTask(500, '2')
addTask(300, '3')
addTask(400, '4')

// 打印顺序是:2 3 1 4

我的分析:

1.Scheduler类的构造函数接收一个参数N,用来控制同时运行的任务;

2.add 接收一个函数参数,并返回一个promise;

3.需要使用一个队列来调度已添加但未运行的任务;

我的实现:

class Scheduler {
    constructor(conut){
        this.count = conut // 同时运行的最大任务数
        this.runCount = 0 // 运行中的任务数
        this.taskQueue = []
    }

    // 运行任务
    static async runTask(task, resolve, reject){
        await task().then(resolve, reject)

        this.runCount --
        if(this.taskQueue.length > 0){
            let item = this.taskQueue.shift()
            Scheduler.runTask.call(this, item.fun, item.resolve, item.reject)
        }
    }

    add(promiseCreator) {
        return new Promise((resolve, reject)=>{
            this.runCount ++
            if(this.runCount > this.count){
                this.taskQueue.push({fun:promiseCreator, resolve, reject})
            }else{
                Scheduler.runTask.call(this, promiseCreator, resolve, reject)
            }
        })
    }
}

运行结果:

其他实现: 

class Scheduler {
    constructor(max) {
        this.max = max;
        this.count = 0; // 用来记录当前正在执行的异步函数
        this.queue = new Array(); // 表示等待队列
    }
    async add(promiseCreator) {
        /*
            此时count已经满了,不能执行本次add需要阻塞在这里,将resolve放入队列中等待唤醒,
            等到count<max时,从队列中取出执行resolve,执行,await执行完毕,本次add继续
        */
        if (this.count >= this.max) {
            await new Promise((resolve, reject) => this.queue.push(resolve));
        }

        this.count++;
        let res = await promiseCreator();
        this.count--;
        if (this.queue.length) {
        // 依次唤醒add
        // 若队列中有值,将其resolve弹出,并执行
        // 以便阻塞的任务,可以正常执行
        this.queue.shift()();
        }
        return res;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值