package org.andork.util; import java.util.LinkedList; import java.util.function.Consumer; public class Batcher2<T> implements Consumer<T> { private final Object lock = new Object(); private LinkedList<T> queue = new LinkedList<T>(); private int maxSize = Integer.MAX_VALUE; private boolean busy; private Consumer<Runnable> runner; private Consumer<LinkedList<T>> handler; private Consumer<T> interruptor; public Batcher2(Consumer<Runnable> runner, Consumer<LinkedList<T>> handler) { super(); this.runner = runner; this.handler = handler; } @Override public void accept(T t) { synchronized (lock) { LinkedList<T> queueToHandle; synchronized (lock) { if (queue.size() < maxSize) { queue.add(t); if (!busy) { busy = true; queueToHandle = this.queue; this.queue = new LinkedList<>(); } else { queueToHandle = null; } } else { queueToHandle = null; } } if (queueToHandle != null) { runner.accept(() -> { LinkedList<T> currentQueue = queueToHandle; while (currentQueue != null) { try { handler.accept(currentQueue); } catch (Exception ex) { ex.printStackTrace(); } synchronized (lock) { if (queue.isEmpty()) { currentQueue = null; busy = false; } else { currentQueue = queue; queue = new LinkedList<>(); } } } }); } else { if (interruptor != null) { interruptor.accept(t); } } } } public Consumer<T> getInterruptor() { return interruptor; } public int getMaxSize() { return maxSize; } public boolean isBusy() { synchronized (this) { return busy; } } public void setInterruptor(Consumer<T> interruptor) { this.interruptor = interruptor; } public void setMaxSize(int maxSize) { this.maxSize = maxSize; } }