com.github.phantomthief.collection.impl.BatchConsumeBlockingQueueTrigger Maven / Gradle / Ivy
package com.github.phantomthief.collection.impl;
import static com.github.phantomthief.concurrent.MoreFutures.scheduleWithDynamicDelay;
import static com.github.phantomthief.util.MoreLocks.runWithLock;
import static com.github.phantomthief.util.MoreLocks.runWithTryLock;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.util.concurrent.MoreExecutors.shutdownAndAwaitTermination;
import static com.google.common.util.concurrent.Uninterruptibles.putUninterruptibly;
import static java.lang.Integer.max;
import static java.lang.Math.min;
import static java.util.concurrent.TimeUnit.DAYS;
import static org.slf4j.LoggerFactory.getLogger;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
import org.slf4j.Logger;
import com.github.phantomthief.collection.BufferTrigger;
import com.github.phantomthief.util.ThrowableConsumer;
/**
* {@link BufferTrigger}基于阻塞队列的批量消费触发器实现.
*
* 该触发器适合生产者-消费者场景,缓存容器基于{@link LinkedBlockingQueue}队列实现.
*
* 触发策略类似Kafka linger,批处理阈值与延迟等待时间满足其一即触发消费回调.
* @author w.vela
*/
public class BatchConsumeBlockingQueueTrigger implements BufferTrigger {
private static final Logger logger = getLogger(BatchConsumeBlockingQueueTrigger.class);
private final BlockingQueue queue;
private final int batchSize;
private final ThrowableConsumer, Exception> consumer;
private final BiConsumer> exceptionHandler;
private final ScheduledExecutorService scheduledExecutorService;
private final ReentrantLock lock = new ReentrantLock();
private final AtomicBoolean running = new AtomicBoolean();
private final Runnable shutdownExecutor;
private volatile boolean shutdown;
BatchConsumeBlockingQueueTrigger(BatchConsumerTriggerBuilder builder) {
Supplier linger = builder.linger;
this.batchSize = builder.batchSize;
this.queue = new LinkedBlockingQueue<>(max(builder.bufferSize, batchSize));
this.consumer = builder.consumer;
this.exceptionHandler = builder.exceptionHandler;
this.scheduledExecutorService = builder.scheduledExecutorService;
Future> future = scheduleWithDynamicDelay(scheduledExecutorService, linger, () -> doBatchConsumer(TriggerType.LINGER));
this.shutdownExecutor = () -> {
future.cancel(false);
if (builder.usingInnerExecutor) {
shutdownAndAwaitTermination(builder.scheduledExecutorService, 1, DAYS);
}
};
}
/**
* 该方法即将废弃,可更换为{@link com.github.phantomthief.collection.BufferTrigger#batchBlocking}.
*/
@Deprecated
public static BatchConsumerTriggerBuilder