控制并发数
题目
实现一个带并发限制的异步调度器Scheduler,保证同时运行的任务最多有两个。完善下面代码的Scheduler类,使以下程序能够正常输出:
class Scheduler {
add(promiseCreator) { ... }
// ...
}
function task(delay, msg) {
return () =>
new Promise((res, rej) => {
setTimeout(() => {
console.log(msg);
res(msg);
}, delay);
});
}
const t1 = task(1000, "1");
const t2 = task(500, "2");
const t3 = task(300, "3");
const t4 = task(400, "4");
const scheduler = new Scheduler(2);
scheduler.add(t1);
scheduler.add(t2);
scheduler.add(t3);
scheduler.add(t4);
// output: 2 3 1 4
整个的完整执行流程:
起始1、2两个任务开始执行
500ms时,2任务执行完毕,输出2,任务3开始执行
800ms时,3任务执行完毕,输出3,任务4开始执行
1000ms时,1任务执行完毕,输出1,此时只剩下4任务在执行
1200ms时,4任务执行完毕,输出4
答案
class Scheduler {
constructor(maxCount) {
this.queue = [];
this.maxCount = maxCount;
this.runningCount = 0;
}
add(promiseCreator) {
this.queue.push(promiseCreator);
this.runTask();
}
runTask() {
if (this.queue.length > 0 && this.runningCount < this.maxCount) {
const task = this.queue.shift();
this.runningCount++;
task().then(() => {
this.runningCount--;
this.runTask();
});
}
}
}
非递归:
class Scheduler {
constructor(maxCount) {
this.queue = [];
this.maxCount = maxCount;
this.runningCount = 0;
}
async add(promiseCreator) {
// 用来设置阻塞(resolve不被执行,await后面的就不会加入到微任务队列)
if (this.runningCount >= this.maxCount) {
await new Promise((resolve) => this.queue.push(resolve));
}
this.runningCount++;
await promiseCreator();
this.runningCount--;
// 打开一个阻塞
this.queue.length && this.queue.shift()();
}
}
考察点
递归调用
异步
Last updated