具有BlockingQueue和返回值或异常的生产者/消费者模式

时间:2015-12-06 18:25:55

标签: java producer-consumer

我正在处理生产者/消费者模式,我的生产者应该等待可能是结果对象或异常的答案。 这样做的最佳方法是什么? 我阅读了很多关于这种模式的例子,但每次制作人都不会介意返回值或消费者例外。

public class BlockingQueueExample {

    public static void main(String[] args) throws Exception {

        BlockingQueue queue = new ArrayBlockingQueue(1024);
        Producer producer = new Producer(queue);
        Consumer consumer = new Consumer(queue);
        new Thread(producer).start();
        new Thread(consumer).start();
        Thread.sleep(4000);
    }
}

public class Producer implements Runnable{

    protected BlockingQueue queue = null;

    public Producer(BlockingQueue queue) {
        this.queue = queue;
    }

    public void run() {
        try {
            queue.put(new Job("test"));
            //here I need the job result or exception
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class Consumer implements Runnable{

    protected BlockingQueue queue = null;

    public Consumer(BlockingQueue queue) {
        this.queue = queue;
    }

    public void run() {
        while(true){
            queue.take();
            try{
                // ... my job
                Result obj;
                // I have to return to producer the result!
            }catch(Exception e){
                //In case of exception I have to return the exception to the producer.
            }
        }
    }
}

MIND:可以有多个Producer和Consumer。

我现在唯一的选择是使用带有此对象的队列:

public class Job{

    private String input;
    private Exception exception;
    private String result;

    public Jon(String input){
        this.input=input;
        this.exception=null;
    }

    public void setException(Exception exception){
        this.exception=exception;
    }

    public Exception getException(){
        return this.exception;
    }

    public void setResult(String result){
        this.result=result;
    }

    public Exception getResult(){
        return this.result;
    }
}

让procuder回读其结果或异常。 否则我应该使用FutureTask的BlockingQueue吗?

2 个答案:

答案 0 :(得分:0)

首先,帮自己一个忙,开始使用泛型。这不应该是BlockingQueue,应该是BlockingQueue<Job>。这个。是。 2015。

其次,你需要两个队列。一个队列用于为您的消费者提供输入,另一个队列用于从他们那里收集输出。因此,您可以使用BlockingQueue<String>作为输入队列,并且可以将Job重命名为Result并为输出队列设置BlockingQueue<Result>

当然,当您的生产者被阻止等待从输入队列中读取结果时,您无法将内容添加到输出队列,因此您需要为生产者设计不同的设计。但这并不比你现在所处的情况更糟糕,在那里你(错误地)期望把一份工作放在一个队列中,并以某种方式(神奇地?)在同一循环中收到结果。

答案 1 :(得分:0)

您应该将作业排队与结果获取分开。为了实现这一点,您可以创建一个队列并从使用者线程向其添加结果。因此,您将需要一个负责结果处理的消费者。