在生产者 - 消费者模型中关闭队列的最有效对象是什么?

时间:2017-01-10 12:05:58

标签: java multithreading producer-consumer

在生产者 - 消费者模型中(一个线程生成项目,将其置于阻塞队列中,另一个线程在无限循环中使用它们),建议通过发送导致循环中断的毒物对象来关闭线程。

Afaik,这可以通过使用:

来完成
  • null(一般不鼓励,BlockingQueue禁止)
  • 生产者不会创造的价值(需要额外的测试,可能会蒸发一些脑细胞)
  • 一个包装器类型,并将每个生成的值放在一个包含值作为唯一属性的类中,并设置为null以指示关闭(例如,Guava框架的Optional)(需要昂贵的对象分配)对于每个生产的项目)
  • 添加到类中的额外属性(用作项目类型)(使模型非常不灵活)
  • 由生成器创建的类型的子类,它仅用于中毒对象(不适用于最终类,需要一个额外的类,它可以是私有的,不消耗明显的空间,但是是一个缺点)< / LI>
  • 中断线程不允许清除队列。

我正在为任意队列项寻找类型安全的解决方案。

2 个答案:

答案 0 :(得分:0)

好的,这就是我要做的事情:

我将定义一个所有消息都需要实现的接口:

public interface Message {
    public default boolean continueProcessing() {
        return true;
    }
}

然后是一个Poison枚举类:

public enum Poison implements Message {
    INSTANCE;

    @Override
    public boolean continueProcessing() {
        return false;
    }
}

消费者代码如下所示:

@Override
public void run() {
    while (true) {
        Message msg = queue.take();
        if (!msg.continueProcessing()) {
            break;
        }
        doSomethingWith(msg);
    }
}

答案 1 :(得分:0)

您可以使用毒丸。价值无关紧要:

制片:

class Producer{
    public static final ItemType POISON = new ItemType();

    // rest goes here
}

消费者:

class Consumer{
    void run(){
         for(;;){
              ItemType item = queue.take();
              if( item == Producer.POISON ) // <- not checking value of item here!
                  break;
              handleItem( item );
         }
    }
}

这也适用于类似Integer的类型,如果您确保POISON 高速缓存,则可以对其进行高速缓存。

在不知道你的ItemType实际是什么的情况下,这是我向你建议的最好的(恕我直言)。

我想到的另一个想法是在Producer上引入一个字段,表示在清空队列后不再需要Item。这意味着以某种方式对消费者代码中的空队列进行额外检查。这也意味着你不能阻塞空队列......在实现这个时要考虑很多。