I’m using java.util.concurrent.BlockingQueue in a very simple producer-consumer scenario. E.g. this pseudo code depicts the consumer part:
class QueueCo
You can wrap your generic object into a dataobject. On this dataobject you can add additional data like the poison object status. The dataobject is a class with 2 fields. T complexObject;
and boolean poison;
.
Your consumer takes the data objects from the queue. If a poison object is returned, you close the consumer, else you unwrap the generic and call 'process(complexObject)'.
I'm using a java.util.concurrent.LinkedBlockingDeque
so that you can add object at the end of the queue and take them from the front. That way your object will be handled in order, but more important it's safe to close the queue after you run into the poison object.
To support multiple consumers, I add the poison object back onto the queue when I run into it.
public final class Data {
private boolean poison = false;
private T complexObject;
public Data() {
this.poison = true;
}
public Data(T complexObject) {
this.complexObject = complexObject;
}
public boolean isPoison() {
return poison;
}
public T getComplexObject() {
return complexObject;
}
}
public class Consumer implements Runnable {
@Override
public final void run() {
Data data;
try {
while (!(data = queue.takeFirst()).isPoison()) {
process(data.getComplexObject());
}
} catch (final InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
// add the poison object back so other consumers can stop too.
queue.addLast(line);
}
}