package org.nutz.runner;
import java.util.Date;
import org.nutz.lang.Times;
import org.nutz.log.Log;
import org.nutz.log.Logs;
/**
* 封装Runnable的带lock的启动器
*
* @author zozoh(zozohtnt@gmail.com)
* @author pw
* @author wendal
*/
public abstract class NutRunner implements Runnable {
protected Log log;
/**
* 所属的关联线程
*/
protected Thread myThread;
/**
* 本运行器名称
*/
protected String rnm;
/**
* 线程锁
*/
protected NutLock lock;
/**
* 累积启动次数
*/
protected int count;
/**
* 本次睡眠时间
*/
protected long interval;
/**
* 报错以后睡眠时间
*/
protected int sleepAfterError;
/**
* 启动于
*/
protected Date upAt;
/**
* 睡眠于,如果本值不为 null,表示本线程正在睡眠,否则为运行中
*/
protected Date downAt;
/**
* 新建一个启动器
*
* @param rname
* 本启动器的名称
*/
public NutRunner(String rname) {
this.rnm = rname;
this.count = 0;
this.sleepAfterError = 30;
this.lock = new NutLock();
}
/**
* 设置报错以后睡眠时间(单位秒)
*
* @param sec
* 秒
* @return 冷却时间
*/
public NutRunner setSleepAfterError(int sec) {
this.sleepAfterError = sec;
return this;
}
/**
* 主逻辑,用户代码不应该覆盖.
*/
public void run() {
if (log == null) {
log = Logs.get().setTag(rnm);
}
myThread = Thread.currentThread();
beforeStart(this);
doIt();
afterStop(this);
}
/**
* 具体的业务实现,返回一个sleep数
*
* @return 本次运行后还需要等待多少个毫秒
*/
public abstract long exec() throws Exception;
/**
* 注册本对象到线程管理器,已废弃
*
* @param me
* 本对象
*/
@Deprecated
public void reg(NutRunner me) {}
/**
* 从线程管理器反注册,已废弃
*
* @param me
* 本对象
*/
@Deprecated
public void unreg(NutRunner me) {}
/**
* 开始之前,一般做一些准备工作,比如资源初始化等
*
* @param me
* runner本身
*/
public void beforeStart(NutRunner me) {
reg(me);
}
/**
* 停止之后,一般是做一些资源回收
*
* @param me
* runner本身
*/
public void afterStop(NutRunner me) {
unreg(me);
}
/**
* 做一些需要定期执行的操作
*/
protected void doIt() {
while (!lock.isStop()) {
synchronized (lock) {
try {
// 修改一下本线程的时间
upAt = Times.now();
downAt = null;
log.debugf("%s [%d] : up", rnm, ++count);
// 执行业务
interval = exec();
if (interval < 1)
interval = 1; // 不能间隔0或者负数,会死线程的
// 等待一个周期
downAt = Times.now();
log.debugf("%s [%d] : wait %ds(%dms)", rnm, count, interval / 1000, interval);
lock.wait(interval);
}
catch (InterruptedException e) {
log.warn(String.format("%s has been interrupted", rnm), e);
break;
}
catch (Throwable e) {
log.warn(String.format("%s has some error", rnm), e);
try {
lock.wait(sleepAfterError * 1000);
}
catch (Throwable e1) {
log.warn(String.format("%s has some error again", rnm), e);
break;
}
}
}
}
}
/**
* 返回格式为 [名称:总启动次数] 最后启动时间:最后休眠时间 - 休眠间隔
*/
public String toString() {
return String.format("[%s:%d] %s/%s - %d",
rnm,
count,
upAt == null ? "NONE" : Times.sDT(upAt),
downAt == null ? "NONE" : Times.sDT(downAt),
interval);
}
/**
* 是否正在等待运行
*
* @return true,如果正在等待
*/
public boolean isWaiting() {
return null != downAt;
}
/**
* 是否正在执行用户代码
*
* @return true,如果正在exec方法内部
*/
public boolean isRunning() {
return null == downAt;
}
/**
* 获取执行间隔
*
* @return 执行间隔
*/
public long getInterval() {
return interval;
}
/**
* 获取最后启动时间
*
* @return 最后启动时间
*/
public Date getUpAt() {
return upAt;
}
/**
* 获取最后一次等待开始的时间
*
* @return 最后一次等待开始的时间
*/
public Date getDownAt() {
return downAt;
}
/**
* 获取本启动器的名称
*
* @return 本启动器的名称
*/
public String getName() {
return rnm;
}
/**
* 获取累计的启动次数
*
* @return 总启动次数
*/
public int getCount() {
return count;
}
/**
* 获取线程NutLock锁
*
* @return 线程NutLock锁
*/
public NutLock getLock() {
return lock;
}
/**
* 获取所属线程是否存活
*
* @return 所属线程是否存活
*/
public boolean isAlive() {
if (myThread != null) {
return myThread.isAlive();
}
return false;
}
/**
* 强行关闭所属线程
*
* @param err
* 传给Thread.stop方法的对象
*/
@SuppressWarnings("deprecation")
public void stop(Throwable err) {
myThread.stop(err);
}
}