java RedoHandler
package org.rx.bot.util; import lombok.Getter; import lombok.Setter; import org.jetbrains.annotations.NotNull; import org.rx.core.Disposable; import org.rx.core.Tasks; import org.rx.util.function.BiAction; import java.util.concurrent.DelayQueue; import java.util.concurrent.Delayed; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import static org.rx.core.App.quietly; import static org.rx.core.App.require; public class RedoHandler<T> extends Disposable { public static class RedoData<T> implements Delayed { @Getter @Setter private T data; private long delayMillis, elapsedTime; @Getter @Setter private volatile boolean done; private final AtomicInteger redoCount = new AtomicInteger(); public RedoData(T data, long delayMillis) { this.data = data; this.delayMillis = delayMillis; renew(); } private RedoData<T> renew() { elapsedTime = System.currentTimeMillis() + delayMillis; return this; } @Override public long getDelay(@NotNull TimeUnit unit) { return unit.convert(elapsedTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS); } @Override public int compareTo(@NotNull Delayed o) { // return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS)); // // 过期时间长的放置在队列尾部 // if (this.getDelay(TimeUnit.MICROSECONDS) > o.getDelay(TimeUnit.MICROSECONDS)) { // return 1; // } // // 过期时间短的放置在队列头 // if (this.getDelay(TimeUnit.MICROSECONDS) < o.getDelay(TimeUnit.MICROSECONDS)) { // return -1; // } // return 0; return Long.compare(this.getDelay(TimeUnit.MICROSECONDS), o.getDelay(TimeUnit.MICROSECONDS)); } } @Setter private int maxRedoCount = 1; private final DelayQueue<RedoData<T>> queue = new DelayQueue<>(); public RedoHandler(BiAction<RedoData<T>> redoCallback) { require(redoCallback); Tasks.run(() -> { while (!isClosed()) { RedoData<T> redoData = queue.take(); if (redoData.done || redoData.redoCount.get() >= maxRedoCount) { continue; } redoData.redoCount.incrementAndGet(); quietly(() -> redoCallback.invoke(redoData)); queue.offer(redoData.renew()); } }); } @Override protected void freeObjects() { } public RedoData<T> monitor(T data, long redoMillis) { RedoData<T> redoData = new RedoData<>(data, redoMillis); queue.offer(redoData); return redoData; } }