两个队列,一个队列并发1,另一个队列并发3

时间:2018-10-19 17:20:53

标签: javascript node.js concurrency queue async.js

我遇到这种情况:

const q1 = async.queue((task,cb) => task(cb), 1);
const q2 = async.queue((task,cb) => task(cb), 3);

基本上,情况是-如果我可以锁定q1,则在q2中我最多可以同时处理3件事。 aka,我程序中的大多数事情都必须串行运行,但是当然事情可以并行运行,但前提是必须先在q1上获得“锁定”。但是,编写此文件比预期要难得多。我认为这类似于读取器/写入锁定问题。 https://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock

换句话说,如果我在q1上有锁,那么我只能处理q2中的事物。实现此问题的一个问题是,如果我始终必须在q2的关键部分中获得对q1的锁定,那么我将无法在q2中使用更高的并发级别,它将始终是串行的。

我现在唯一的想法是翻转一个布尔值,像这样:

let q2HasLock = false;

if(q2hasLock === true){
  q2.push(cb => ...);
}
else{
  q1.push(cb => ...);
}

然后我可以使用它:

q2.drain = () => {
   q2HasLock = false;
};

但是剩下的部分是我不知道如何/何时将q2HasLock翻转到true。希望您了解问题/想法。此实现的另一个问题是,推送到q2的请求可能会饿死要发送到q1的请求,因此我可以这样做:

let q2HasLock = false, count = 0 ;

if(q2hasLock === true && count < 3){
  count++;
  q2.push(cb => ...);
}
else{
  q1.push(cb => ...);
}

q2.drain = () => {
   count = 0;
   q2HasLock = false;
};

这变得毛茸茸-我想尽可能简单地实现它!

1 个答案:

答案 0 :(得分:0)

好的,这应该满足要求,但是最好找到一种比这更简单的方法:

    const async = require('async');
    const q1 = async.queue((task, cb) => task(cb), 1);
    const q2 = async.queue((task, cb) => task(cb), 3);

    const map = new Map();
    let count = 0;

    const getProm = function (q) {

      if (!map.has(q)) {
        map.set(q, new Promise(resolve => {

          q1.push(cb => {
            resolve();  // 'lock' on q1 has been obtained, nothing can use q1 until we release the lock by calling cb().
            q.drain = () => {
              q.drain = null;
              count = 0;
              map.delete(q);
              cb();
            };
          });

        }));
      }

      return map.get(q);

    };


 if(foo && count < 5){
   return getProm(q2).then(v => {

      q2.push(cb => {
        setTimeout(cb, 140);
      });

    });
 }

 return q1.push(cb => {
      setTimeout(cb, 30);
    });

这是做什么的-一次只能运行一种类型的任务,但是如果任务类型是foo,则可以同时运行3种。 count < 5检查确保q1请求不会被q2请求饿死。

这里的窍门是使用诺言。兑现承诺后,尽管在这种情况下我们不需要该值,但您仍然可以使用决议值致电promise.then()

为了获得更高的性能,我们可以使用布尔标志代替promise,但是逻辑要复杂得多。