【带并发限制的异步调度器Ⅰ】原始Demo

实现 Scheduler 中的 add 方法,满足:

  1. add 方法只有一个入参 task , 类型为 () => Promise<any>
  2. 按 add 调用顺序执行任务
  3. 同一时刻只能存在至多2个并发任务
  4. 可自由添加实例属性、方法

题目代码:

class Scheduler {
  add(promiseMaker) {

  }
}

const scheduler = new Scheduler();
const addTask = (time, text) => {
  const promiseMaker = () => new Promise(resolve => {
    setTimeout(() => {
      console.log(text);
      resolve();
    }, time);
  });
  Scheduler.add(promiseMaker);
};
addTask(1000, '1');
addTask(500, '2');
addTask(300, '3');
addTask(400, '4'); 

// 最终打印 2 3 1 4

解决思路:

  1. 题目要求“按 add 调用顺序执行任务”,说明添加的任务会先保存进队列里(先进先出),而不是堆栈(后进先出),因此保存任务使用的数据结构为数组
  2. “同一时刻只能存在至多2个并发任务”,这里的关键题干是“同一时刻”,“2个并发任务”,再结合(1),可以想到Scheduler里会存在2个存放任务的数组,一个保存正在执行任务的数组doingFuncs ,当任务执行完成,从数组doingFuncs中移除任务(不用按照在数组里存在的顺序移除,谁先完成谁先移除),一个保存待执行任务的数组funcs,以及一个最大执行任务数maxFunNum。
  3. 两个数组之间的关系:当doingFuncs其中一个任务执行完成时,会从funcs头部取出一个任务塞入doingFuncs,那怎么表达一个任务执行完成呢?题目中任务的数据类型是promise,promise不管结果是成功还是失败,都会在then中处理执行完成之后的事务,因此事务主要处理2件事:
    (1)从doingFuncs中移除任务
    (2)从funcs中拿出一个任务,放入doingFuncs中执行

解决方案:

class Scheduler {
  constructor() {
    this.funcs = []; //待执行的任务
    this.doingFuncs = []; //正在执行的任务数
    this.maxFunNum = 2;  //最大执行任务数
  }

  add(promiseMaker) {
    if (this.doingFuncs.length < this.maxFunNum) {
      this.run(promiseMaker);
    } else {
      this.funcs.push(promiseMaker);
    }
  }

  run(promiseMaker) {
    let arrayLength = this.doingFuncs.push(promiseMaker);
    let index = arrayLength - 1;
    promiseMaker().then(() => {
      this.doingFuncs.splice(index, 1);
      if (this.funcs.length > 0) {
        this.run(this.funcs.shift());
      }
    })
  }
}

const scheduler = new Scheduler();
const addTask = (time, text) => {
  const promiseMaker = () => new Promise(resolve => {
    setTimeout(() => {
      console.log(text);
      resolve();
    }, time);
  });

  scheduler.add(promiseMaker);
};
addTask(1000, '1');
addTask(500, '2');
addTask(300, '3');
addTask(400, '4'); 

// 最终打印 2 3 1 4

结语:
这个代码编程题是我在面试字节跳动的时候遇到的,然后感觉很有趣但当时并没有实现,就把它记录下来,自己花时间实现了。其实了解这机制并不困难,重要的是如何举一反三,把机制用于实践中,因此根据这个机制我做了一个点餐排队系统。
更新在后续文章中。【新】点餐排队系统Demo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容