
shz.core.accept.Acceptor Maven / Gradle / Ivy
package shz.core.accept;
import shz.core.ThreadHelp;
import shz.core.AccessibleCacheHelp;
import java.util.Collection;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public abstract class Acceptor {
private final String threadName;
private Executor executor;
private final Lock lock;
private final Condition sleep;
private final Condition finish;
private final Condition delay;
private volatile boolean stop = true;
private volatile boolean wait;
protected Acceptor(String threadName) {
this.threadName = threadName;
lock = new ReentrantLock();
sleep = lock.newCondition();
finish = lock.newCondition();
delay = lock.newCondition();
}
protected Acceptor() {
this.threadName = AccessibleCacheHelp.identify(getClass());
lock = new ReentrantLock();
sleep = lock.newCondition();
finish = lock.newCondition();
delay = lock.newCondition();
}
protected long gapMillis() {
return 0L;
}
protected long gapSleepMillis() {
return 50L;
}
protected abstract boolean acceptable();
protected void log(Throwable cause) {
cause.printStackTrace();
}
protected abstract void execute();
protected long sleepMicros() {
return 0L;
}
protected boolean stoppable() {
return false;
}
protected long finishMillis() {
return 0L;
}
protected void finishCallback() {
}
protected long delayMicros() {
return 5000L;
}
private void run() {
while (!stop) {
if (!lock.tryLock()) break;
try {
long idleMillis = 0L, gapMillis = gapMillis(), gapSleepMillis = gapSleepMillis();
if (gapMillis > 0L) gapSleepMillis = Math.min(gapMillis, gapSleepMillis <= 0 ? 50L : gapSleepMillis);
else gapSleepMillis = 0L;
while (!stop) {
boolean acceptable = false;
try {
acceptable = acceptable();
} catch (Throwable e) {
log(e);
}
if (!acceptable) {
//无消费数据
if (gapSleepMillis == 0L || idleMillis >= gapMillis) break;
try {
TimeUnit.MILLISECONDS.sleep(gapSleepMillis);
} catch (InterruptedException ignored) {
}
//累计空闲时间
idleMillis += gapSleepMillis;
continue;
}
//重置空闲时间
idleMillis = 0L;
try {
//执行消费方法
execute();
} catch (Throwable e) {
log(e);
}
try {
long time = sleepMicros();
//消费睡眠
if (time > 0L) sleep.await(time, TimeUnit.MICROSECONDS);
} catch (Throwable e) {
log(e);
}
}
//判断是否结束线程任务
if (!stop) try {
stop = stoppable();
} catch (Throwable e) {
log(e);
}
if (!stop) {
wait = true;
if (!stop) {
long finishMillis = 100L;
long curMillis = System.currentTimeMillis();
try {
//当前没有可消费,等待被唤醒或等待超时
finishMillis = finishMillis();
//执行回调
finishCallback();
} catch (Throwable e) {
log(e);
}
if (finishMillis > 0L) {
long delta = finishMillis + curMillis - System.currentTimeMillis();
finishMillis = delta != 0L ? delta : 100L;
} else finishMillis = 0L;
if (wait) {
try {
if (finishMillis > 0L) finish.await(finishMillis, TimeUnit.MILLISECONDS);
else if (finishMillis == 0L) finish.await();
} catch (InterruptedException e) {
log(e);
}
wait = false;
}
long delayMicros = 0L;
try {
delayMicros = delayMicros();
} catch (Throwable e) {
log(e);
}
if (delayMicros > 0L && finishMillis < 0L) {
long delta = delayMicros + finishMillis;
delayMicros = delta > 0 ? delta : 100L;
}
try {
if (delayMicros > 0L) delay.await(delayMicros, TimeUnit.MICROSECONDS);
} catch (InterruptedException e) {
log(e);
}
}
}
} finally {
lock.unlock();
}
}
}
protected final void accept() {
if (!stop || !lock.tryLock()) return;
try {
if (!stop) return;
stop = false;
if (executor == null) executor = ThreadHelp.getExecutor(ThreadHelp.TPConfig
.of(threadName)
.tpType(ThreadHelp.TPType.SINGLE_THREAD_EXECUTOR)
.daemon(true)
.workQueue(new LinkedBlockingQueue<>(1)));
executor.execute(this::run);
} finally {
lock.unlock();
}
}
protected final void awaken() {
if (!wait || !lock.tryLock()) return;
try {
if (!wait) return;
wait = false;
finish.signal();
} catch (Throwable t) {
log(t);
} finally {
lock.unlock();
}
}
public final boolean isStop() {
return stop;
}
public final synchronized void stop() {
if (!stop) {
stop = true;
awaken();
}
}
public final void push(T t) {
if (offer(t)) {
accept();
awaken();
}
}
protected abstract boolean offer(T t);
public final void push(Collection dataset) {
if (offer(dataset)) {
accept();
awaken();
}
}
protected boolean offer(Collection dataset) {
boolean flag = false;
for (T t : dataset) {
boolean offer = offer(t);
if (!flag) flag = offer;
}
return flag;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy