最近有个小功能,需求是多线程写,单线程读。
考虑采用AtomLong作为写的指针,用一个2的N次方长度的数组作为Buffer的存储,超出后自动循环,不扩容。
读由于是单线程,采用普通long作为指针即可。
代码如下:
private T[] buffer;
private int remMask;
private long readPointer=0;
private AtomicLong writePointer=new AtomicLong(0);
public NolockObjectBuffer(int bufferSizeTimes,Class<T> clz) {
buffer = (T[])Array.newInstance(clz,1<<bufferSizeTimes);
remMask = buffer.length-1;
}
@Override
public List readBufferData() {
long start=readPointer;
long end=writePointer.get();
while(end-start>buffer.length){
start=end-buffer.length;
}
List<T> result=new ArrayList<T>((int)(end-start));
for(long i=start;i<end;i++){
result.add(buffer[getBufferPos(i)]);
}
readPointer=end;
return result;
}
private int getBufferPos(long pointer){
return (int)pointer&remMask;
}
@Override
public void putBufferData(T data) {
buffer[getBufferPos(writePointer.getAndIncrement())]=data;
}
@Override
public Stream<T> stream() {
long start=readPointer;
long end=writePointer.get();
List<T> result=new ArrayList<T>((int)(end-start));
for(long i=start;i<end;i++){
result.add(buffer[getBufferPos(i)]);
}
return result.stream();
}
比如统计远程接口调用的平均耗时,用Buffer记录每个请求的访问耗时,然后定期Get一下进行最大、最小、平均的计算。