在应用程序中, 有时并不希望只是为了存储某些数据而引入数据库这个大载体, 在文件下载服务器中, 可以用一个 List记录某IP, 或者某用户在最近一段时间内所读取的流量.
新建一个用于存放流量的列表:
列表的长度:
再者, 该列表有一个长度, 它指示该表由几个槽组成, 这里假设存储近30分钟的量, 由10个槽组成, 每一个槽存放3分钟之内的量.
setLink(); 方法由多线程在完成数据读取后调用.
另外需要有一个监视线程来跟据时间近迁移, 重新重置trough里的数据. 比如近3分钟时间内如果没有数据流出, 那么最老的一项需要被重置.
那么在程序运行过程中, 可以读取该列表的总长度, 来获取近30分钟内的流量, 这个实现不是精确的, 但对于统计来说, 已经够用了.
新建一个用于存放流量的列表:
/** A list for storing recently past 30 minutes reads */
static final List<UserDescriptor> LINKED =
new ArrayList<UserDescriptor>(LINKED_SIZE);
列表的长度:
/** The capaity to initiate LINKED */
private static final int LINKED_SIZE = 0xa;
再者, 该列表有一个长度, 它指示该表由几个槽组成, 这里假设存储近30分钟的量, 由10个槽组成, 每一个槽存放3分钟之内的量.
setLink(); 方法由多线程在完成数据读取后调用.
void setLink(long transferedSize) {
if (transferedSize <= 0) {
return;
}
long reads = transferedSize;
synchronized (LINKED) {
if (pointer < 0 || pointer >= LINKED_SIZE) {
// error encounter.
pointer = 0;
}
UserDescriptor ud = LINKED.get(pointer);
if (ud.lastUpdate == 0) {
ud.setDescriptor(reads);
LOG.debug("add new Link point at: " + pointer + " reads: " + reads);
} else {
if (now() - ud.lastUpdate < INTERVAL_UPDATE_LINK) {
// inner the time trough, increase reads !!
ud.addReads(reads);
LOG.debug("addLink point at: " + pointer + " reads: " + ud.reads);
} else {
// out of the time trough, point to the next one
pointer = (pointer + 1) % LINKED_SIZE;
ud = LINKED.get(pointer);
ud.reset();
ud.setDescriptor(reads);
LOG.debug("setLink point at: " + pointer + " reads: " + ud.reads);
}
}
}
}
另外需要有一个监视线程来跟据时间近迁移, 重新重置trough里的数据. 比如近3分钟时间内如果没有数据流出, 那么最老的一项需要被重置.
void truncate(List<? extends Descriptor> link, int _point) {
if (link.size() == 0) {
return;
}
if (_point < 0 || _point >= link.size()) {
_point = 0;
}
long now = now();
int size = link.size();
int _low = size - 1;
while (_low != -1) {
if (_point -1 < 0) {
_point = size;
}
int _p = --_point;
Descriptor dscpt = link.get(_p);
long lastUpdate = dscpt.getLastUpdate();
if (lastUpdate != 0) {
if (now - lastUpdate >= LINKED_WINDOW_SIZE) {
LOG.info("*XXXXX descriptor will be reset " + dscpt);
dscpt.reset();
}
}
--_low;
}
}
那么在程序运行过程中, 可以读取该列表的总长度, 来获取近30分钟内的流量, 这个实现不是精确的, 但对于统计来说, 已经够用了.