【前端面试高频手撕】使用js实现任务并发调度

  • 题目解读
    实现一个可以限制任务执行并发数的Class类,其实就是类似于模拟事件循环执行栈和任务队列之间的运转,但是有一点点不一样的是:事件循环是等执行栈中的任务全部执行完毕后再去任务队列中查看异步任务(单线程,不能同时执行多个任务);而这个题目要实现的效果是,只要当前执行任务数没有超过最高并发限制,就要去队列中取任务出来执行(n线程,n由用户决定)
  • 实现思路
    维护三个变量:最大调度数n、执行栈正在执行的任务数count,等待队列queue。
    每次有新任务进来时,先判断当前是否已达最高并发限制,若达到就将当前任务阻塞(这里将任务包装为一个promise,只要内部没有resolve,promise就没有结果,就会处于阻塞状态,将resolve放进任务队列进行排队)并放进任务队列中排队;若没有达到最高并发限制,就执行任务,执行完任务后去任务队列拿出队首任务的resolve并调用,解除阻塞,执行任务。
class Scheduler {
    constructor(max){
        // 最大调度数
        this.max=max;
        // 执行栈执行任务数
        this.count=0;
        // 等待队列
        this.queue = [];
    }
    async add(promiseCreator){
        // 如果执行栈已满,则阻塞当前任务
        if(this.count>=this.max) await new Promise((resolve)=>this.queue.push(resolve))

        // 执行当前函数 count+1表示当前执行站加一个任务执行
        this.count++
        const res = await promiseCreator()
        //count-1表示任务执行完毕,执行栈少一个任务
        this.count--

        // 已执行完一个任务,所以执行栈一定有坑,查看任务队列是否有任务排队
        // 取出任务调用resolve解锁阻塞
        if(this.queue.length){
            this.queue.shift()()
        }
    }
  }
     
  const timeout = time => new Promise(resolve => {
    setTimeout(resolve, time);
  })
    
  const scheduler = new Scheduler(2);
    
  const addTask = (time,order) => {
    //add返回一个promise,参数也是一个promise
    scheduler.add(() => timeout(time)).then(()=>console.log(order))
  }
  
  addTask(1000, '1');
  addTask(500, '2');
  addTask(300, '3');
  addTask(400, '4');
  
// output: 2 3 1 4

  • 案例输出解释
    • 最初,任务一、二进入执行栈开始执行,任务三、四进入任务队列排队
    • 500ms时,任务二执行完毕(打印2),任务三解除阻塞,进入执行栈执行
    • 500ms+300ms时,任务三执行完毕(打印3),任务四解除阻塞,进入执行栈执行
    • 500ms+300ms+200ms时(打印1),任务一执行完毕
    • 500ms+300ms+200ms+200ms时(打印4),任务四执行完毕
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值