public class DisruptorQueue<T> extends AbstractQueue<T> {
private final EventTranslatorOneArg translator;
private final RingBuffer ringBuffer;
private final Disruptor disruptor;
private final int bufferSize;
private static final int RINGBUFFER_DEFAULT_SIZE = 4 * 1024;
public DisruptorQueue(EventFactory eventFactory , EventTranslatorOneArg translator , DisruptorEventHandler eventHandler) {
super(eventHandler);
bufferSize = getBufferSize();
Disruptor disruptor = new Disruptor<>(eventFactory, bufferSize,
new ThreadUtils(getClass().getSimpleName()), ProducerType.MULTI, new BlockingWaitStrategy());
disruptor.handleEventsWith(eventHandler);
this.translator = translator;
this.ringBuffer = disruptor.getRingBuffer();
this.disruptor = disruptor;
}
@Override
public void publish(T item) {
if (!ringBuffer.tryPublishEvent(translator, item)) {
ringBuffer.publishEvent(translator, item);
}
}
@Override
public void start() {
super.start();
disruptor.start();
}
@Override
public void close() {
super.close();
disruptor.shutdown();
}
@Override
public int size() {
return bufferSize - (int) ringBuffer.remainingCapacity();
}
private static int getBufferSize() {
return RINGBUFFER_DEFAULT_SIZE;
}
}
public abstract class DisruptorEventHandler<T> implements EventHandler<EventHolder<T>> {
protected final boolean allowDiscard = true;
private final AtomicBoolean running = new AtomicBoolean(false);
private final AtomicLong failCount = new AtomicLong(0);
public void onEvent(EventHolder eventHolder, long sequence, boolean endOfBatch) {
T event = eventHolder.getEvent();
if (event != null && isRunning()) {
handleEvent(event, endOfBatch);
}
eventHolder.setEvent(null);
}
public abstract void handleEvent(T eventItem, boolean endOfBatch);
public boolean isRunning() {
return running.get();
}
public void start() {
running.getAndSet(true);
}
public void close() {
running.getAndSet(false);
}
protected void incrementFailCount(long delta) {
failCount.addAndGet(delta);
}
public long getFailCount() {
return failCount.get();
}
}