并发任务控制
摘要:代码结构 timeout函数 返回一个 Promise,在指定时间后 resolve。 SuperTask类 属性 maxParallelCount:最大并发数。 taskList:待执行任务队列。 currentTask:当前运行任务数。 方法 add(task :将任务包装成 Promise,加入队列,并触发任务执行。 _run( :根据并发限制从队列中取出任务执行,并在任务完成后触发后续任务。 addTask函数 调用 SuperTask 实例添加任务,并在任务完成后打印日志。...
代码结构
timeout函数
- 返回一个 Promise,在指定时间后 resolve。
SuperTask类
属性
maxParallelCount:最大并发数。taskList:待执行任务队列。currentTask:当前运行任务数。
方法
add(task):将任务包装成 Promise,加入队列,并触发任务执行。_run():根据并发限制从队列中取出任务执行,并在任务完成后触发后续任务。
addTask函数
- 调用
SuperTask实例添加任务,并在任务完成后打印日志。
执行流程分析
- 初始化:创建
SuperTask实例,设置最大并发数为 2。 - 添加任务:依次添加 6 个任务(每个任务通过
timeout(100000)模拟耗时操作)。 - 任务调度:
- 第一批次:任务 1 和任务 2 立即执行(
currentTask从 0 增至 2)。 - 剩余任务(3-6)暂存于
taskList。
- 第一批次:任务 1 和任务 2 立即执行(
- 任务完成处理:
- 任一任务完成时,
currentTask减 1,并调用_run()启动新任务。 - 后续任务按队列顺序依次执行,始终保持最多 2 个任务并发。
- 任一任务完成时,
并发控制逻辑
_run()方法:通过循环检查并发数和队列长度,逐个取出任务执行。- 每个任务执行后,通过
finally确保无论成功与否都更新状态并触发后续任务。
- 每个任务执行后,通过
- 队列管理:任务按添加顺序执行,确保先进先出(FIFO)。
时间与输出分析
时间线
0-100 秒:任务 1 和任务 2 并行执行,100 秒后同时完成。
100-200 秒:任务 3 和任务 4 启动并执行,完成后触发输出。
- 200-300 秒:任务 5 和任务 6 启动并执行,完成后触发输出。
输出顺序
- 每组任务的完成日志按添加顺序输出(如任务 1 和 2 几乎同时完成,但
.then()回调按任务触发顺序执行)。
潜在问题
- 输出顺序确定性:
- 虽然任务按批次完成,但同一批次内(如任务 1 和 2)的日志输出顺序可能受事件循环影响,不过代码逻辑保证了任务按添加顺序执行。
- 错误处理:
- 任务失败时仍会触发后续任务,符合预期。
结论
- 代码正确实现了并发控制,确保最多 2 个任务同时运行,任务按添加顺序分批次执行。
- 测试用例中的 6 个任务将分三批完成,每批耗时约 100 秒,总时间约 300 秒,输出顺序按任务编号递增。
// 并发任务控制
function timeout(time){
return new Promise((resolve) => {
setTimeout(resolve, time)
})
}
class SuperTask{
constructor(maxParallelCount = 2){
this.maxParallelCount = maxParallelCount; // 最大并发数
this.taskList = []; // 任务列表
this.currentTask = 0; // 正在运行数量
}
add(task){
return new Promise((resolve, reject) => {
this.taskList.push({task, resolve, reject})
this._run();
})
}
_run(){
while(this.currentTask < this.maxParallelCount && this.taskList.length){
const {task, resolve, reject} = this.taskList.shift()
this.currentTask++;
Promise.resolve(task()).then(resolve, reject).finally(() => {
this.currentTask--;
this._run()
})
}
}
}
const superTask = new SuperTask();
function addTask(time, task){
superTask
.add(()=>{timeout(time)})
.then(()=>{
console.log(`任务${task}完成`)
})
}
addTask(100000, 1);
addTask(100000, 2);
addTask(100000, 3);
addTask(100000, 4);
addTask(100000, 5);
addTask(100000, 6);
本文链接:https://blog.smallhao.fun/?id=14 转载需授权!
Chen’Blog版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!