org.rx.core.WheelTimer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rxlib Show documentation
Show all versions of rxlib Show documentation
A set of utilities for Java
package org.rx.core;
import io.netty.util.HashedWheelTimer;
import io.netty.util.Timeout;
import io.netty.util.Timer;
import io.netty.util.TimerTask;
import io.netty.util.internal.ThreadLocalRandom;
import lombok.*;
import org.rx.bean.$;
import org.rx.bean.FlagsEnum;
import org.rx.util.function.Action;
import org.rx.util.function.Func;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.LongUnaryOperator;
import static org.rx.bean.$.$;
import static org.rx.core.Sys.proxy;
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
public class WheelTimer extends AbstractExecutorService implements ScheduledExecutorService {
//schedule 抛出异常会终止
// public final class ScheduledThreadPool extends ScheduledThreadPoolExecutor {
// final String poolName;
//
// public ScheduledThreadPool() {
// super(RxConfig.INSTANCE.threadPool.scheduleInitSize, ThreadPool.newThreadFactory("schedule"));
// this.poolName = "schedule";
//
// ThreadPool.SIZER.register(this, ThreadPool.DEFAULT_CPU_WATER_MARK);
// }
//
// @Override
// public String toString() {
// return poolName;
// }
// }
class Task implements TimerTask, TimeoutFuture {
final Func fn;
final FlagsEnum flags;
final Object id;
final LongUnaryOperator nextDelayFn;
final String traceId;
final StackTraceElement[] stackTrace;
long delay;
long expiredTime;
volatile Timeout timeout;
volatile Future future;
long p0, p1;
Task(Func fn, FlagsEnum flags, Object id, LongUnaryOperator nextDelayFn) {
if (flags == null) {
flags = TimeoutFlag.NONE.flags();
}
RxConfig conf = RxConfig.INSTANCE;
if (conf.threadPool.traceName != null) {
flags.add(TimeoutFlag.THREAD_TRACE);
}
if (conf.trace.slowMethodElapsedMicros > 0 && ThreadLocalRandom.current().nextInt(0, 100) < conf.threadPool.slowMethodSamplingPercent) {
stackTrace = new Throwable().getStackTrace();
} else {
stackTrace = null;
}
this.fn = fn;
this.flags = flags;
this.id = id;
this.nextDelayFn = nextDelayFn;
traceId = ThreadPool.CTX_TRACE_ID.get();
}
@SneakyThrows
@Override
public synchronized void run(Timeout timeout) throws Exception {
boolean traceFlag = flags.has(TimeoutFlag.THREAD_TRACE);
if (traceFlag) {
ThreadPool.startTrace(traceId);
}
ThreadPool.CTX_STACK_TRACE.set(stackTrace != null ? stackTrace : Boolean.TRUE);
try {
future = executor.submit(() -> {
boolean doContinue = flags.has(TimeoutFlag.PERIOD);
try {
return fn.get();
} finally {
if (ThreadPool.continueFlag(doContinue)) {
newTimeout(this, delay, timeout.timer());
} else if (id != null) {
holder.remove(id);
}
}
});
} finally {
ThreadPool.CTX_STACK_TRACE.remove();
if (traceFlag) {
ThreadPool.endTrace();
}
}
notifyAll();
}
@Override
public String toString() {
String hc = id != null ? id.toString() : Integer.toHexString(hashCode());
return String.format("TimeTask-%s[%s]", hc, flags.getValue());
}
@Override
public Timer timer() {
return timeout.timer();
}
@Override
public TimerTask task() {
return timeout.task();
}
@Override
public boolean isExpired() {
return timeout.isExpired();
}
@Override
public boolean isCancelled() {
return timeout.isCancelled();
}
@Override
public boolean cancel() {
return cancel(true);
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
if (future != null) {
future.cancel(mayInterruptIfRunning);
}
if (timeout != null) {
//Timeout maybe null when parallel invoke tasks of the same id
return timeout.cancel();
}
return true;
}
@Override
public boolean isDone() {
return future != null && future.isDone();
}
@Override
public T get() throws InterruptedException, ExecutionException {
synchronized (this) {
if (future == null) {
wait();
}
}
if (future == null) {
throw new InterruptedException();
}
return future.get();
}
@Override
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
synchronized (this) {
if (future == null) {
wait(TimeUnit.MILLISECONDS.convert(timeout, unit));
}
}
if (future == null) {
throw new TimeoutException();
}
return future.get(timeout, unit);
}
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(expiredTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed o) {
if (!(o instanceof Task)) {
return 0;
}
long otherExpiredTime = ((Task>) o).expiredTime;
return Long.compare(expiredTime, otherExpiredTime);
}
}
class EmptyTimeout implements Timeout, TimerTask {
@Override
public Timer timer() {
return timer;
}
@Override
public TimerTask task() {
return this;
}
@Override
public boolean isExpired() {
return true;
}
@Override
public boolean isCancelled() {
return true;
}
@Override
public boolean cancel() {
return true;
}
@Override
public void run(Timeout timeout) throws Exception {
}
}
static final long TICK_DURATION = 100;
static final Map