import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;public class BatchQueue<T> {
private static final Logger log = LoggerFactory.getLogger(BatchQueue.class);
private final int batchSize;
private final Consumer<List<T>> consumer;
private final int timeoutInMs;private AtomicBoolean isLooping = new AtomicBoolean(false);
private BlockingQueue<T> queue = new LinkedBlockingQueue<>();
private final ThreadPoolExecutor executorService;
private AtomicLong start = new AtomicLong(System.currentTimeMillis());public BatchQueue(int batchSize, int timeoutInMs, Consumer<List<T>> consumer, ThreadPoolExecutor executorService) {
this.batchSize = batchSize;
this.timeoutInMs = timeoutInMs;
this.consumer = consumer;
this.executorService = executorService;}
public BatchQueue(int batchSize, int timeoutInMs, Consumer<List<T>> consumer) {
this(batchSize, timeoutInMs, consumer, new ThreadPoolExecutor(1, 20,
60L, TimeUnit.SECONDS,
new SynchronousQueue<>(), new ThreadPoolExecutor.CallerRunsPolicy()));
}public boolean add(T t) {
boolean result = queue.add(t);
if (!isLooping.get() && result) {
isLooping.set(true);
startLoop();
}
return result;
}public void completeAll() {
while (!queue.isEmpty()) {
drainToConsume();
}
}private void startLoop() {
executorService.execute(new HandleThread());
}private void drainToConsume() {
List<T> drained = new ArrayList<>();
int num = queue.drainTo(drained, batchSize);
if (num > 0) {
consumer.accept(drained);
start.set(System.currentTimeMillis());
}
}private class HandleThread implements Runnable {
@Override
public void run() {
start = new AtomicLong(System.currentTimeMillis());
while (true) {
long last = System.currentTimeMillis() - start.get();
if (queue.size() >= batchSize || (!queue.isEmpty() && last > timeoutInMs)) {
try {
drainToConsume();
} catch (Exception e) {
log.error("batchQueue批处理异常:", e);
} catch (Throwable e) {
log.error("batchQueue批处理error:", e);
}
} else if (queue.isEmpty()) {
isLooping.set(false);
break;
}
}
}
}
}
java 批处理,定时处理队列
于 2021-12-22 14:54:56 首次发布