JS控制任务并发数
最近经常看到面经中分享的一道题
class Scheduler {
constructor(concurrency = 2) {
this.concurrency = concurrency; // 最大并发数
this.count = 0; // 当前运行时的任务数
this.waitingPool = []; // 任务等待池
}
async add(task) {
// TODO: 待实现
}
}
// 初始化一个限流器实例
const scheduler = new Scheduler(2);
// 模拟耗时任务
const timeout = (time) => new Promise(r => setTimeout(r, time));
const addTask = (time, order) => {
scheduler.add(()=>timeout(time))
.then(()=>console.log(order))
}
addTask(1000, 1);
addTask(500, 2);
addTask(300, 3);
addTask(400, 4);
addTask(300, 5);
思考
- 如何控制并发数?
- 当前队列满时如何暂停后面任务执行,空时如何执行后面任务?
实现
class Scheduler {
constructor(concurrency = 2) {
// 并发上限
this.concurrency = concurrency;
// 运行中的任务数
this.count = 0;
// 任务列表
this.waitingPool = [];
}
addTask(task) {
return new Promise((resolve, reject) => {
// 添加任务到队列里
this.waitingPool.push({
task,
resolve,
reject,
});
// 添加任务之后立即进入执行
this._run();
});
}
_run() {
// 当任务列表不为空 且 正在运行的任务不超过并发上限 则继续执行下一个任务
while (this.waitingPool.length > 0 && this.count < this.concurrency) {
// 队列拿最新的任务
const { task, resolve, reject } = this.waitingPool.shift();
// 运行计数 +1
this.count++;
// 运行任务
const res = task();
// 判断任务是异步还是同步任务
if (res instanceof Promise) {
res.then(resolve, reject).finally(() => {
// 执行结束 运行计数 -1
this.count--;
// 递归调用 run 执行下一个任务
this._run();
});
} else {
// 执行结束 运行计数 -1
this.count--;
// 递归调用 run 执行下一个任务
this._run();
}
}
}
}