- 题目解读
实现一个可以限制任务执行并发数的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))
this.count++
const res = await promiseCreator()
this.count--
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) => {
scheduler.add(() => timeout(time)).then(()=>console.log(order))
}
addTask(1000, '1');
addTask(500, '2');
addTask(300, '3');
addTask(400, '4');
- 案例输出解释
- 最初,任务一、二进入执行栈开始执行,任务三、四进入任务队列排队
- 500ms时,任务二执行完毕(打印2),任务三解除阻塞,进入执行栈执行
- 500ms+300ms时,任务三执行完毕(打印3),任务四解除阻塞,进入执行栈执行
- 500ms+300ms+200ms时(打印1),任务一执行完毕
- 500ms+300ms+200ms+200ms时(打印4),任务四执行完毕