com.github.phantomthief.collection.impl.SimpleBufferTrigger Maven / Gradle / Ivy
package com.github.phantomthief.collection.impl;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Throwables.throwIfUnchecked;
import static com.google.common.util.concurrent.MoreExecutors.shutdownAndAwaitTermination;
import static java.lang.System.currentTimeMillis;
import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import static java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.LongSupplier;
import java.util.function.Supplier;
import java.util.function.ToIntBiFunction;
import org.slf4j.Logger;
import com.github.phantomthief.collection.BufferTrigger;
import com.github.phantomthief.util.ThrowableConsumer;
/**
* {@link BufferTrigger}的通用实现,适合大多数业务场景
*
* 消费触发策略会考虑消费回调函数的执行时间,实际执行间隔 = 理论执行间隔 - 消费回调函数执行时间;
* 如回调函数执行时间已超过理论执行间隔,将立即执行下一次消费任务.
*
* @author w.vela
*/
public class SimpleBufferTrigger implements BufferTrigger {
private static final Logger logger = getLogger(SimpleBufferTrigger.class);
private static final long DEFAULT_NEXT_TRIGGER_PERIOD = TimeUnit.SECONDS.toMillis(1);
private final String name;
private final AtomicLong counter = new AtomicLong();
private final ThrowableConsumer consumer;
private final ToIntBiFunction queueAdder;
private final Supplier bufferFactory;
private final BiConsumer exceptionHandler;
private final AtomicReference buffer = new AtomicReference<>();
private final LongSupplier maxBufferCount;
private final RejectHandler rejectHandler;
private final ReadLock readLock;
private final WriteLock writeLock;
private final Condition writeCondition;
private final Runnable shutdownExecutor;
private volatile boolean shutdown;
private volatile long lastConsumeTimestamp = currentTimeMillis();
/**
* 使用提供的构造器创建SimpleBufferTrigger实例
*/
SimpleBufferTrigger(SimpleBufferTriggerBuilder builder) {
this.name = builder.name;
this.queueAdder = builder.queueAdder;
this.bufferFactory = builder.bufferFactory;
this.consumer = builder.consumer;
this.exceptionHandler = builder.exceptionHandler;
this.maxBufferCount = builder.maxBufferCount;
this.rejectHandler = builder.rejectHandler;
this.buffer.set(this.bufferFactory.get());
if (!builder.disableSwitchLock) {
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
readLock = lock.readLock();
writeLock = lock.writeLock();
writeCondition = writeLock.newCondition();
} else {
readLock = null;
writeLock = null;
writeCondition = null;
}
builder.scheduledExecutorService.schedule(
new TriggerRunnable(builder.scheduledExecutorService, builder.triggerStrategy),
DEFAULT_NEXT_TRIGGER_PERIOD, MILLISECONDS);
this.shutdownExecutor = () -> {
if (builder.usingInnerExecutor) {
shutdownAndAwaitTermination(builder.scheduledExecutorService, 1, DAYS);
}
};
}
/**
* 该方法即将废弃,可更换为{@link BufferTrigger#simple()}创建适合大多数场景的通用实例.
*/
@Deprecated
public static SimpleBufferTriggerBuilder