有一些程序是永不停歇的,比如监控某个数据表中的内容是否变化。若有变化通知给其他程序。下面两个类可以作为模版。
/**
* 定期检查某个数据库中某表中的数据是否有变,若有更新,做想做的事。这是抽象基类。
* 泛型V代表 表中 每一行数据对应的对象。
*/
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public abstract class DBWorkerBase implements Runnable {
private static final Logger logger = LoggerFactory
.getLogger(DBWorkerBase.class);
private static final ScheduledExecutorService ses = new ScheduledThreadPoolExecutor(
10);
// for the running task
private int period;
private ScheduledFuture future = null;
/** 对应数据库中某张表的最后更新时间,由子类实现赋值 */
private long lastTimestamp = -1;
// used for the data storing
private volatile List data = new ArrayList();
/** 最近一次从数据库获取新数据的时间 */
private volatile long lastFetchTimestamp = 0;
/** run()执行后有没有得到已经变化的新数据 ,供子类使用*/
protected boolean doesUpdateinMethodRUN = false;
public DBWorkerBase(int periodBySecond) {
this.period = periodBySecond;
}
/**
* Start the worker.
*/
public void start() {
if (isStarted()) {
return;
}
// 立即执行,然后每隔period执行一次
future = ses.scheduleWithFixedDelay(this, 0, period, TimeUnit.SECONDS);
}
/**
* Stop the worker.
*/
public void stop() {
if (isStarted()) {
future.cancel(true);
future = null;
}
}
private boolean isStarted() {
if (future == null) {
return false;
}
if (future.isDone()) {
future = null;
return false;
}
return true;
}
@Override
public void run() {
doesUpdateinMethodRUN = false;
// check if we need update
long diff = System.currentTimeMillis() - lastFetchTimestamp;
// 检查表的时间戳是否有变
if (!checkUpdate()) {
return;
}
doesUpdateinMethodRUN = true;
try {
data = doTask();
lastFetchTimestamp = System.currentTimeMillis();
} catch (Exception e) {
logger.error("fail to do the task", e);
return;
}
}
protected abstract long getLastTime() throws Exception;
/**
* Check if we need to retrieve the data again.
* @return
*/
protected boolean checkUpdate() {
long newTime = -1;
try {
newTime = getLastTime();
} catch (Exception e) {
logger.error("fail to get last and timestamp", e);
return true;
}
boolean needUpdate = false;
if ((newTime != lastTimestamp)) {
// has changed
needUpdate = true;
// update the timestamp
this.lastTimestamp = newTime;
}
return needUpdate;
}
/**
* Every DB worker needs to implement the doTask to get the data from db.
* @return
*/
protected abstract List doTask() throws Exception;
public List getData() {
return data;
}
}
/**
* 定期检查Student表中的数据是否有变,若有更新,做想做的事。这是子类。
*/
import java.util.ArrayList;
import java.util.List;
public class StudentWorker extends DBWorkerBase {
private DatasourceDAOImpl dao = new DatasourceDAOImpl();
public StudentWorker(int period) {
super(period);
}
@Override
public void run() {
super.run();
// 若果得到了新数据,更新拼凑的EPL对应的数据库
if (doesUpdateinMethodRUN) {
// 自己想做的事
}
}
@Override
public List doTask() throws Exception {
return dao.getStudents(null);
}
@Override
protected long getLastTime() throws Exception {
return dao.getLastModifiedTime().getTime();
}
}