实现ringbuffer,不需要用锁的方法,如下面:
用write read size 以及start end就可以定位问题
写入过程,总共6种情况:
1)write = read ,如果end-write >len 那么write = write + len 写入长度len
如果end-write <len 需要借用前面的位置,那么write = len-(end-write),写入长度len
2)write > read ,并且 end-write>len,那么write = write + len,写入长度为len
3)write < read, 并且 read-write>len,那么write = write+ len,写入长度为len
4)write走到队尾的情况,并且write > read,并且(end-write)+(read-start)>len,那么write = len-(end-write)
其余情况,无法写入数据。
读入过程,总共五种情况,也是一样的,如下:
1)write = read 无法读数据
2)write > read 情况 如果write - read > len 那么read = read+ len
如果write - read < len ,那么无法读数据
3)write<read情况,说明写的快,如果end-read > len ,read = read+ len
如果end-read< len && (end-read) + (write-start)>len,那么read= len-(end-read)
通过上述的分析可以发现,基本的场景就可以分析了,下面是java的demo,读取二机制,
这种很适合在实时流的缓冲设计,
但是有一个小问题,最后总是小于读取的len是无法读取的,
对于c++也可以参考实现,就是首地址,采取malloc,然后将地址传入就ok了!
请读者自行参考实现,不再写代码!
import java.io.File;
import java.io.FileInputStream;import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
//环形数组缓冲区 缓冲区所能存放的数据为缓冲区大小的个数 减去1 为实际能存储的大小
public class RingBuffer {
private static byte[] buf=null;
private static int mStart;
private static int mEnd;
private static int mSize;
private static int mWrite;
private static int mRead;
//mSize = BUFFER_SIZE;
//mAddrEnd = mAddrStart + BUFFER_SIZE;
// mAddrWrite = mAddrStart;
// mAddrRead = mAddrStart;
public RingBuffer(int s){//构造函数定义缓冲区的大小
buf = new byte[s];
mSize=buf.length;
mRead = mWrite = 0;
mStart=0;
mEnd=buf.length-1;
System.out.println("buf.length="+buf.length);
}
public boolean put(byte[] ar,int len){
int read = mRead;
int write = mWrite;
int end = mEnd;
int start = mStart;
if((read == write) ||
((read > write) && ((read - write) > len)) ||
((read < write) && ((end - write > len))))
{
System.arraycopy(ar, 0, buf, write,len);
mWrite=mWrite + len;
System.out.println("<<<<<<<<<<<<<<<<<<write<<<<<<<<<<<<<<<<<<<<<<<<");
System.out.println("len = "+len);
System.out.println("read="+mRead);
System.out.println("write="+mWrite);
System.out.println(">>>>>>>>>>>>>>>>>>>write>>>>>>>>>>>>>>>>>>>>>>>");
return true;
}
else if((read < write) && (((end - write) + (read - start)) > len))
{
//memcpy((void*)write, (void*)buffer, (end - write));
//memcpy((void*)start, (void*)(buffer + (end - write)),len - (end - write));
System.arraycopy(ar,0, buf,write,end-write);
System.arraycopy(ar, start, buf, end-write, len-(end-write));
System.out.println("write="+mWrite);
mWrite= mWrite+len-mSize;
System.out.println("===============write====================");
System.out.println("len = "+len);
System.out.println("read="+mRead);
System.out.println("write="+mWrite);
System.out.println("===============write====================");
return true;
}
else
{
System.out.println("写的空间不够!!!!!");
System.out.println("len = "+len);
System.out.println("read="+mRead);
System.out.println("write="+mWrite);
System.out.println("start="+mStart);
System.out.println("end="+mEnd);
System.out.println("写的空间不够!!!!!");
return false;
}
}
public byte[] get(int push_unit){
int read = mRead;
int write = mWrite;
int end = mEnd;
int start = mStart;
/*if(read - mRead <= push_unit)
{
byte[] arr = new byte[write - read];
System.out.println("push_unit = "+(write - read));
System.arraycopy(buf,read, arr,0,write - read);
mRead = mWrite;
System.out.println("====55555555555555555555555=======");
System.out.println("read="+mRead);
System.out.println("write="+mWrite);
System.out.println("====5555555555555555555555===========");
return arr;
}*/
byte[] arr = new byte[push_unit];
if((write > (read + push_unit)) ||
((write < read) && ((end - read) > push_unit)))
{
//memcpy((void*)out_buffer, (void*)read, push_unit);
//this.mRead = (unsigned char*)(read + push_unit);
System.arraycopy(buf,read, arr,0,push_unit);
mRead = mRead + push_unit;
System.out.println("-----------------read----------------------");
System.out.println("get_unit = "+push_unit);
System.out.println("read="+mRead);
System.out.println("write="+mWrite);
System.out.println("-----------------read-----------------------");
return arr;
}
else if((write < read) && (((write - start) + (end - read)) > push_unit))
{
//memcpy((void*)out_buffer, (void*)read, (int)(end - read));
//memcpy((void*)((unsigned int) out_buffer + end - read), (void*)start, (int)(push_unit - (end-read)));
//this.mRead = (unsigned char*)((read + push_unit) - mSize);
System.arraycopy(buf,read, arr,0,end-read);
System.arraycopy(buf,start, arr,end-read,push_unit-(end-read));
mRead = mRead + push_unit - mSize;
System.out.println("@@@@@@@@@@@@@@@@@@read@@@@@@@@@@@@@@@@@@@@@@@@@@@");
System.out.println("get_unit = "+push_unit);
System.out.println("read="+mRead);
System.out.println("write="+mWrite);
System.out.println("@@@@@@@@@@@@@@@@@@read@@@@@@@@@@@@@@@@@@@@@@@@@@@");
return arr;
}
else
{
System.out.println("读的空间不够!");
System.out.println("get_unit = "+push_unit);
System.out.println("read="+mRead);
System.out.println("write="+mWrite);
System.out.println("读的空间不够!");
return null;
}
}
public void reset_buffer() {
mStart=0;
mEnd=mStart+mSize;
mSize=buf.length;
mRead = mWrite = mStart;
System.out.println("buf.length=%d"+buf.length);
}
public static void main(String[] args){//测试
final RingBuffer ringbuf = new RingBuffer(1024*1024*100);
InputStream in = null;
new Thread() {
public void run() {
System.out.println("线程执行了。。。。。。。");
//RingBuffer test = new RingBuffer(1048576);
int push_unit = 1024*1024;
byte[] getbytes = new byte[1024*1024];
try {
sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
File out_file = new File("F:/newfile.ts");
FileOutputStream fop = null;
try {
if (!out_file.exists()) {
out_file.createNewFile();
}
fop = new FileOutputStream(out_file);
for(int i =0;i<10000000;i++){
do{
getbytes = ringbuf.get(push_unit);
if(getbytes == null)
{
sleep(10);
}
// if file doesnt exists, then create it
if(getbytes != null)
fop.write(getbytes);
/*if(getbytes.length != push_unit){
fop.flush();
fop.close();
return;
}*/
}while(getbytes != null);
}
}catch (Exception e1) {
e1.printStackTrace();
} finally {
if (fop != null) {
try {
fop.close();
} catch (IOException e1) {
}
}
}
}
}.start();
try {
System.out.println("以字节为单位读取文件内容,一次读多个字节:");
// 一次读多个字节
String fileName = "F:/[MV] KARA - Jet Coaster Love (Dance Ver.) [1080p HD].webm";
byte[] tempbytes = new byte[1024*1024];
int byteread = 0;
in = new FileInputStream(fileName);
//getbytes = buf.get(push_unit);
File out = new File("F:/out.ts");
FileOutputStream op = null;
if (!out.exists()) {
out.createNewFile();
}
op = new FileOutputStream(out);
//showAvailableBytes(in);
// 读入多个字节到字节数组中,byteread为一次读入的字节数
while ((byteread = in.read(tempbytes)) != -1) {
//op.write(tempbytes);
if(ringbuf.put(tempbytes,byteread)==false){
//System.out.println("空间不够");
return ;
}
}
} catch (Exception e1) {
e1.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e1) {
}
}
}
}
}