当前位置: 首页 > news >正文

一道并发的面试题,控制并发数量

文章目录

    • 题目要求
    • 解析题目
    • 总结发现
    • 补全SuperTask代码,实现逻辑
    • 完整代码和结果

题目要求

在这里插入图片描述

解析题目

我们先看看这道题目的规律,看到前两个,还是挺正常的,任务1 10s后输出,任务 2 5s后输出。
任务3 却是8s后输出,但明明传入的是3s,可结果是8s后输出,这里其实我们就该考虑到,这个8s那来的,结合前面两个,可以想到,5 + 3 正好8s,所以这个任务3是等任务2执行完后在执行的。
再往下看任务4 这里传入4s,却是12s后输出的,很明显就是 8 + 4 的结果,所以任务4是在任务2和任务3执行的,而任务5 却是15s后输出,那就是在任务1 后执行的。

总结发现

如下所示
在这里插入图片描述

其实可以联想到,这里有两条任务线在并发执行,任务1 由于10s后才输出,任务2 是5s后输出,所以任务3 会排在任务2后面执行,这就是为啥任务3 明明传入3s,但结果是8s后才输出了,依次类推,任务4接上,到任务5时,任务1执行完毕,此时任务2那条线,任务4在执行占用,所以任务5接在任务1后执行。

补全SuperTask代码,实现逻辑

class SuperTask {constructor(parallelNum = 2) {this.parallelNum = parallelNum // 最大并发数this.taskList = [] // 存储任务线this.runNum = 0 // 正在执行的任务数}add(task) {// 不管怎样,先把任务存在数组里面,由于外面是.then,所以这里是promise,为了执行任务的时候,执行结束要回调,所以把resolve,reject也保存起来return new Promise((resolve, reject) => {this.taskList.push({task,resolve,reject,})// 存进来的时候调下执行函数this._run()})}_run() {// 如果正在执行的数量 小于 最大并发数 并且 存储任务线大于0, 那么就执行存储任务中的任务while (this.runNum < this.parallelNum && this.taskList.length) {// 拿出来任务,并删除存储任务线的数据const { task, resolve, reject } = this.taskList.shift()// 因为外面的timeout方法返回的是一个promise,所以这里是异步需要.thentask().then(resolve, reject).finally(() => {// 执行完了,正在执行任务数要--,并且再次调用下执行函数this.runNum--this._run()})// 这里正在执行的任务数要++this.runNum++}}
}

完整代码和结果

class SuperTask {constructor(parallelNum = 2) {this.parallelNum = parallelNum // 最大并发数this.taskList = [] // 存储任务线this.runNum = 0 // 正在执行的任务数}add(task) {// 不管怎样,先把任务存在数组里面,由于外面是.then,所以这里是promise,为了执行任务的时候,执行结束要回调,所以把resolve,reject也保存起来return new Promise((resolve, reject) => {this.taskList.push({task,resolve,reject,})// 存进来的时候调下执行函数this._run()})}_run() {// 如果正在执行的数量 小于 最大并发数 并且 存储任务线大于0, 那么就执行存储任务中的任务while (this.runNum < this.parallelNum && this.taskList.length) {// 拿出来任务,并删除存储任务线的数据const { task, resolve, reject } = this.taskList.shift()// 因为外面的timeout方法返回的是一个promise,所以这里是异步需要.thentask().then(resolve, reject).finally(() => {// 执行完了,正在执行任务数要--,并且再次调用下执行函数this.runNum--this._run()})// 这里正在执行的任务数要++this.runNum++}}
}// 题目要求如下 依次执行addTask函数,输出结果如下 任务1 10s后输出,任务2 5s后输出,任务3 8s后输出,任务4 12s后输出,任务5 15s后输出
const superTask = new SuperTask()function timeout(time) {return new Promise((resolve) => {setTimeout(resolve, time)})
}function addTask(time, name) {superTask.add(() => timeout(time)).then(() => {console.log(`任务${name}完成`)})
}addTask(10000, 1) // 10s后输出
addTask(5000, 2) // 5s后输出
addTask(3000, 3) // 8s后输出
addTask(4000, 4) // 12s后输出
addTask(5000, 5) // 15s后输出// 任务1 (10s后输出) => 任务5 (15s后输出)
// 任务2 (5s后输出) => 任务3 (8s后输出) => 任务4 (12s后输出)

在这里插入图片描述

相关文章:

  • Baklib构建AI就绪型知识中台实践
  • Python中列表相关操作
  • PIL库的图像增强函数
  • Docker中部署Alertmanager
  • 从代码学习数学优化算法 - 拉格朗日松弛 Python版
  • 查看数据库占用磁盘空间的方法
  • JAVA面向对象——对象和类的基本语法
  • 第一章走进java世界
  • 数据库实验——备份与恢复
  • JavaScript 深拷贝:从基础到实践的全面指南
  • 2025年- H38-Lc146 --142.环形链表(快慢指针,快2慢1,快1慢1)--Java版
  • 前端流行框架Vue3教程:21. 插槽(3)
  • C语言| 指针变量的初始化
  • 如何测试北斗卫星通讯终端的性能?
  • DEBUG:Lombok 失效
  • C++类与对象--6 特性二:继承
  • std::vector<>.emplace_back
  • flutter设置最大高度,超过最大高度时滑动显示
  • 使用frp内网穿透本地的虚拟机
  • spring event事件(四)内部事件(1)ApplicationReadyEvent
  • 深一度|有望冲击首轮秀?杨瀚森走出舒适圈站上大舞台
  • 证监会:证券公司要处理好功能性和盈利性关系,切实维护好投资者利益
  • 国家发改委:城市更新项目必须建立多元化多层级资金投入机制
  • 总书记回信二周年之际,上海如何将垃圾分类深度融入城市发展?
  • “当代阿炳”甘柏林逝世,创办了国内第一所残疾人高等学府
  • 哈马斯与以色列在多哈举行新一轮加沙停火谈判