package org.quickbundle.tools.support.buffer;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.quickbundle.config.RmBaseConfig;
import org.quickbundle.tools.support.log.RmLogHelper;
import org.slf4j.Logger;
/**
* 通用缓冲器 <h3>刷新方式:</h3>
* <ul>
* <li>满容刷新(默认)</li>
* <li>过期(超过一定时间未刷新时)刷新,设置expire字段</li>
* <li>定期(到达某一时间点)刷新,设置expire_time字段</li>
* <li>自定义刷新,重写needFlush方法</li>
* </ul>
*
* @author liujia
* @since 2010-10-14
* @param <E> 缓冲对象
*/
public abstract class AbstractTaskQueue<E> {
protected Logger log = RmLogHelper.getLogger(this.getClass());
/**
* 缓冲队列
*/
protected ConcurrentLinkedQueue<E> buf = new ConcurrentLinkedQueue<E>();
/**
* 最大容量
*/
protected int capcity = 1024;
/**
* 上次刷新时间
*/
protected long last_flush = System.currentTimeMillis();
/**
* 最大未刷新时间
*/
protected long expire_interval = RmBaseConfig.getSingleton().getCacheFlushInterval();
/**
* 指定的下次刷新时刻
*/
protected long expire_time = Long.MAX_VALUE/2;
/**
* 刷新锁,防止并发刷新
*/
protected Lock flushLock = new ReentrantLock();
/**
* 构造函数
*/
public AbstractTaskQueue() {
//绑定到刷新器
FlushQueueThread.getSingleton().addTaskQueue(this);
}
/**
* @return 缓冲器名称
*/
public String getName() {
return this.getClass().getName();
}
/**
* 增加内容,刷新时依然可插入
*
* @param e
*/
public void add(E e) {
if(e == null){
return ;
}
if(buf.size() >= capcity * 10){
//容量过大
RmLogHelper.getLogger("rmexception").error("buf.clear() -> count:" + buf.size() + ", 缓冲区溢出, 请联系维护人员检查是否部署环境异常!");
buf.clear();
}
//注释掉以下代码,杜绝在发起调用的业务线程中更新日志
// if (buf.size() >= 0.1 * capcity) {
// tryFlush();
// }
buf.add(e);
}
/**
* 尝试刷新
*/
public void tryFlush() {
// 防止并发刷新
if (!flushLock.tryLock()) {
return;
}
try {
long startTime = System.currentTimeMillis();
int oldSize = buf.size();
flush(buf);
int thisCount = oldSize-buf.size();
if(thisCount > 0) {
log.info("flush " + thisCount + " records, cost " + (System.currentTimeMillis()-startTime) + " ms");
}
} finally {
last_flush = System.currentTimeMillis();
flushLock.unlock();
}
}
/**
* 刷新缓冲区内数据,由子类提供
*/
protected abstract void flush(Queue<E> buf);
/**
* 检查刷新条件 若满足,则刷新缓冲区
*/
public void checkFlush() {
if ((last_flush + expire_interval < System.currentTimeMillis())
|| (expire_time < System.currentTimeMillis())
|| (buf.size() > capcity * 0.1)
|| (needFlush())) {
if (expire_time < System.currentTimeMillis()) {
expire_time = Long.MAX_VALUE / 2;
}
tryFlush();
}
}
/**
* 由子类复写,提供自定义刷新条件
*
* @return
*/
protected boolean needFlush() {
return false;
}
/**
* 得到当前容量
* @return
*/
public int getSize() {
return buf.size();
}
/**
* 得到最大容量
* @return
*/
public int getCapcity() {
return capcity;
}
/**
* 设置最大容量
* @param capcity
*/
public void setCapcity(int capcity) {
this.capcity = capcity;
}
/**
* 得到刷新间隔
* @return
*/
public long getExpire_interval() {
return expire_interval;
}
/**
* 设置刷新间隔
* @param expireInterval
*/
public void setExpire_interval(long expireInterval) {
expire_interval = expireInterval;
}
/**
* 得到刷新到期时间
* @return
*/
public long getExpire_time() {
return expire_time;
}
/**
* 设置刷新到期时间
* @param expireInterval
*/
public void setExpire_time(long expireTime) {
expire_time = expireTime;
}
}