JS实现带并发的异步任务调度器-promise

JS实现带并发的异步任务调度器-promise

问题描述

实现一个具有并发数量限制的异步任务调度器,可以规定最大同时运行的任务。

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


class Scheduler {
  add(promiseCreator) { ... }
  // ...
}
   
const timeout = time => new Promise(resolve => {
  setTimeout(resolve, time);
})
  
const scheduler = new Scheduler(2);
  
const addTask = (time,order) => {
  scheduler.add(() => timeout(time)).then(()=>console.log(order))
  //scheduler.add(() => timeout(time)) 参数是一个promise,返回一个promise
}

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

// output: 2 3 1 4

整个的完整执行流程:

起始1、2两个任务开始执行
500ms时,2任务执行完毕,输出2,任务3开始执行
800ms时,3任务执行完毕,输出3,任务4开始执行
1000ms时,1任务执行完毕,输出1,此时只剩下4任务在执行
1200ms时,4任务执行完毕,输出4

分析

任务调度器-控制任务的执行,当资源不足时将任务加入等待队列,当资源足够时,将等待队列中的任务取出执行

在调度器中一般会有一个等待队列queue,存放当资源不够时等待执行的任务。
具有并发数据限制,假设通过max设置允许同时运行的任务,还需要count表示当前正在执行的任务数量。
当需要执行一个任务A时,先判断count==max 如果相等说明任务A不能执行,应该被阻塞,阻塞的任务放进queue中,等待任务调度器管理。
如果count<max说明正在执行的任务数没有达到最大容量,那么count++执行任务A,执行完毕后count--
此时如果queue中有值,说明之前有任务因为并发数量限制而被阻塞,现在count<max,任务调度器会将对头的任务弹出执行。

实现

阻塞的方法:采用new一个Promise对象,将resolve函数的引用推入队列queue中。只要resolve函数没有被执行,当前任务就会一直阻塞在这里


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;
        
    }
  }
     
  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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值