等待多个qeueues的消费者线程

时间:2018-05-09 16:31:21

标签: java multithreading producer-consumer

我有多个任务队列和一个consumer线程。

一旦任何队列有任务,

Consumer线程就会被唤醒。所以我想知道进行这种沟通的最佳方式是什么。

这些是可以解决这个问题的一些实现,并解释了为什么我想找到不同的东西:

  • 实现这种方法的一种方法是使用一些监视器对象并调用 来自消费者线程的.wait(timeout)并致电.notify() 来自生产者线程。但是,这种方法使用wait/notify 是一种低级API,所以我尽量避免使用它。此外,它并不总是正确的,在某些情况下,我们可能会等待整个超时,而我们还有任务要做(睡觉的理发师问题)。
  • 使用CountDownLatch方法reset之类的方法会很好, 但我在java.util.concurrent找不到类似的东西。实施将相当简单,但实施新自行车是我想要避免的wait/notify。另外我认为它等同于wait/notify方法的整个超时也有同样的问题。
  • 将生成器包装创建实体放入某些Task并使所有生成器写入同一队列,以便使用者可以侦听单个队列。在我认为的大多数情况下,这种方法实际上非常好,但在我的情况下,这部分应用程序具有低延迟要求,因此我必须避免创建新对象(例如这些包装器)并且还会增加队列尾部的争用(而不是一个消费者,所有人都会在那里写)这对延迟也不是很好。

那么有没有其他方法可以实现它?(可能正在使用其他一些并发原语)

1 个答案:

答案 0 :(得分:1)

如何使用任务通知队列,在这种情况下,如果任务队列中的任何一个添加项目,它也会将项目添加到ntification队列。

以下剪辑说明了这种方法:

import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;

public class Main<T1, T2>  {


  Queue<T1> taskType1Queue = new ArrayBlockingQueue<T1>(10);
  Queue<T2> taskType2Queue= new ArrayBlockingQueue<T2>(10);
  ArrayBlockingQueue<Boolean> notificationQueue= new ArrayBlockingQueue<Boolean>(2);


  public void produceType1(T1 task) {
    new Thread(new Runnable() {
      @Override
      public void run() {
        taskType1Queue.add(task);
        notificationQueue.offer(true);; //does not block if full
      }
    });
  }

  public void produceType2(T2 task) {
    new Thread(new Runnable() {
      @Override
      public void run() {
        taskType2Queue.add(task);
        notificationQueue.offer(true); //does not block if full
      }
    });
  }


  public void consume() {

    try {
      notificationQueue.take();//wait till task1 o task2 has been published

      for(;!Thread.currentThread().isInterrupted();){
        T1 task1 = taskType1Queue.poll();//does not block if queue is empty
        if (task1 != null) {
          //do something
        }
        T2 task2 = taskType2Queue.poll();//does not block if queue is empty
        if (task2 != null) {
          //do something
        }
        if(task1 == null && task2 == null) {
          break;
        }
      }

    } catch (InterruptedException e) {
      System.out.println("Consumer thread done");
      return;
    }

  }

}