切换语言为:繁体

JavaScript中实现并发任务控制器

  • 爱糖宝
  • 2024-09-10
  • 2053
  • 0
  • 0

1. 引言

并发任务执行是多线程编程中的一个重要主题,当应用程序需要同时处理多个任务时,如果不加以控制,可能会导致资源过度消耗或系统负载过高。通俗的讲,就是前端有一万个请求,后端一次只能处理五十个,那么要如何控制并发确保系统稳定运行呢?对于前端开发来说,js是单线程机制已经是一个伪命题了,我们通过异步操作,可以合理地限制并发任务的数量,确保系统稳定运行,同时提高资源利用率。 下面是设计思路以及具体实现:

2. 设计并发任务控制器

我们的目标是创建一个类 SuperTask,它可以接受任务并将它们按照指定的并发数量进行调度执行。每个任务都是一个返回 Promise 的函数,这样我们可以轻松地处理异步操作。

2.1 构造函数

类中添加构造函数,初始化 SuperTask 对象的属性:

  • parallelCount:用户可以通过传入参数来设置最大并发数量。默认值为2,用于接下来的测试。

  • tasks:一个数组,用于存储等待执行的任务对象。

  • runningCount:一个计数器,记录当前正在执行的任务数量。

class SuperTask {
  constructor(parallelCount = 2) {
    this.parallelCount = parallelCount; // 并发量
    this.tasks = [];                    // 待执行的任务队列
    this.runningCount = 0;              // 正在运行的任务数量
  }
}

2.2 add 方法

类中添加add 方法,接收一个任务(即返回 Promise 的函数),将其封装成一个任务对象,并添加到任务队列中。之后调用 _run 方法尝试运行队列中的任务。

  // 添加任务到队列
  add(task) {
    return new Promise((resolve, reject) => {
      this.tasks.push({
        task,
        resolve,
        reject
      });

      this._run();
    });
  }

2.3 _run 方法

类中添加_run 方法,这是一个私有方法,用于检查是否有可用的并发槽位,并运行队列中的任务。它的工作流程如下:

  1. 检查当前正在运行的任务数量是否小于最大并发数量。

  2. 如果小于最大并发数量,并且任务队列中有任务,则从队列中取出一个任务并执行。

  3. 执行任务后,无论结果如何(成功或失败),都会调用 .finally() 回调来减少正在运行的任务数量,并再次调用 _run 方法尝试运行队列中的下一个任务。

  // 运行任务队列中的任务
_run() {
    while (this.runningCount < this.parallelCount && this.tasks.length > 0) {
      const { task, resolve, reject } = this.tasks.shift();
      this.runningCount++;
      task().then(resolve, reject).finally(() => {
        this.runningCount--;
        this._run();
      });
    }
  }

2.4 使用示例

假设我们有一个简单的延时函数 timeout,用于模拟异步操作。

function timeout(time) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, time);
  });
}

接下来,我们可以创建一个 SuperTask 实例,并添加一些任务:

const superTask = new SuperTask(); 

function addTask(time, name) {
  superTask.add(() => timeout(time)).then(() => {
    console.log(`任务${name}完成`);
  });
}

addTask(10000, '1');
addTask(2000, '2');
addTask(5000, '3');
addTask(1000, '4');
addTask(7000, '5');
addTask(3000, '6');

总结

并发任务控制器 SuperTask,通过限制并发任务的数量来确保系统的稳定性和效率。该控制器通过维护一个任务队列和一个运行计数器,确保在不超过设定的最大并发数量的前提下,有序地执行任务,从而实现高效的并发控制。并发任务控制器的核心在于_run()的设计,即把任务都装在任务队列里,只取并发量的任务,某任务结束之后,通过递归再从队列里取任务,希望友友们在面试中遇到这类问题可以有一定的思路。

0条评论

您的电子邮件等信息不会被公开,以下所有项均必填

OK! You can skip this field.