Skip to content

Instantly share code, notes, and snippets.

@Coneboy-k
Created June 6, 2018 10:47
Show Gist options
  • Save Coneboy-k/4c0cc857425e32f80a8a0bf1739d28be to your computer and use it in GitHub Desktop.
Save Coneboy-k/4c0cc857425e32f80a8a0bf1739d28be to your computer and use it in GitHub Desktop.
基于HashedWheelTimer 的对象池
@Slf4j
public abstract class AbsTimerItem {
private static final long MIN_TIMEOUT_MILLIS = 1L;
private HashedWheelTimer timer;
private long readerIdleTimeMillis;
private long writerIdleTimeMillis;
private volatile int state; // 0 - none, 1 - initialized, 2 - destroyed
private volatile boolean reading;
private volatile Timeout readerIdleTimeout;
private volatile long lastReadTime;
private boolean firstReaderIdleEvent = true;
private volatile Timeout writerIdleTimeout;
/**
* 默认为秒
*/
public void initTimer(HashedWheelTimer timer, int readerIdleTimeSeconds, int writerIdleTimeSeconds) {
initTimer(timer, readerIdleTimeSeconds, writerIdleTimeSeconds, TimeUnit.SECONDS);
}
public void initTimer(HashedWheelTimer timer, long readerIdleTime, long writerIdleTime, TimeUnit unit) {
Preconditions.checkNotNull(timer, "timer can't be null");
if (unit == null) {
throw new NullPointerException("unit");
}
this.timer = timer;
if (readerIdleTime <= 0L) {
readerIdleTimeMillis = 0L;
} else {
readerIdleTimeMillis = Math.max(unit.toMillis(readerIdleTime), MIN_TIMEOUT_MILLIS);
}
if (writerIdleTime <= 0L) {
writerIdleTimeMillis = 0L;
} else {
writerIdleTimeMillis = Math.max(unit.toMillis(writerIdleTime), MIN_TIMEOUT_MILLIS);
}
}
/**
* 读取超时准备释放资源
*/
public abstract void alreadyTimerOut();
/**
* 改进行写了
*/
public abstract void timeToWrite();
/**
* 开启计时
*/
public void startTimer() {
initialize();
}
/**
* 关闭计时
*/
public void stopTimer() {
destroy();
}
/**
* 现在开始读取数据
*/
public void nowActiveReadingTimer() {
if (readerIdleTimeMillis > 0) {
firstReaderIdleEvent = true;
reading = true;
}
// 读取技术
this.readingFinish();
}
/**
* 读取结束 todo 待优化
*/
private void readingFinish() {
if (readerIdleTimeMillis > 0) {
lastReadTime = SKTools.getNowTimeStamp();
reading = false;
}
}
/**
* 初始化
*/
private void initialize() {
switch (state) {
case 1:
case 2:
return;
}
state = 1;
lastReadTime = SystemClock.now();
if (readerIdleTimeMillis > 0) {
readerIdleTimeout = timer.newTimeout(
new ReaderIdleTimeoutTask(this),
readerIdleTimeMillis, TimeUnit.MILLISECONDS);
}
if (writerIdleTimeMillis > 0) {
writerIdleTimeout = timer.newTimeout(new WriterIdleTimeoutTask(this), writerIdleTimeMillis, TimeUnit.MILLISECONDS);
}
}
/**
* 销毁timer
*/
private void destroy() {
state = 2;
if (readerIdleTimeout != null) {
readerIdleTimeout.cancel();
readerIdleTimeout = null;
}
if (writerIdleTimeout != null) {
writerIdleTimeout.cancel();
writerIdleTimeout = null;
}
}
/**
* 操作超时
*/
private final class ReaderIdleTimeoutTask implements TimerTask {
private final AbsTimerItem timerItem;
ReaderIdleTimeoutTask(AbsTimerItem timerItem) {
this.timerItem = timerItem;
}
@Override
public void run(Timeout timeout) throws Exception {
if (timeout.isCancelled()) {
return;
}
long lastReadTime = AbsTimerItem.this.lastReadTime;
long nextDelay = readerIdleTimeMillis;
if (!reading) {
nextDelay -= SystemClock.now() - lastReadTime;
}
if (nextDelay <= 0) {
// Reader is idle - set a new timeout and notify the callback.
readerIdleTimeout = timer.newTimeout(this, readerIdleTimeMillis, TimeUnit.MILLISECONDS);
try {
//
if (firstReaderIdleEvent) {
firstReaderIdleEvent = false;
// 第一次读等待读超时
log.debug("第一次读等待读超时");
} else {
// 准备 释放资源
log.debug("准备 释放资源");
AbsTimerItem.this.alreadyTimerOut();
}
} catch (Throwable t) {
}
} else {
// Read occurred before the timeout - set a new timeout with shorter delay.
readerIdleTimeout = timer.newTimeout(this, nextDelay, TimeUnit.MILLISECONDS);
}
}
}
/**
* 对写进行判断
*/
private final class WriterIdleTimeoutTask implements TimerTask {
private final AbsTimerItem timerItem;
WriterIdleTimeoutTask(AbsTimerItem timerItem) {
this.timerItem = timerItem;
}
@Override
public void run(Timeout timeout) throws Exception {
if (timeout.isCancelled()) {
return;
}
// 时间到了 直接进行下次
AbsTimerItem.this.timeToWrite();
writerIdleTimeout = timer.newTimeout(this, writerIdleTimeMillis, TimeUnit.MILLISECONDS);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment