BufferedInputStream 源码分析
一、简介
BufferedInputStream会缓存一部分数据(默认8K),这个函数的作用就是读取更多的数据到缓存,必要的时候会扩大缓存的内容。
在该类中有几个重要的标志位:markpos,pos,count
【markpos的作用,marklength区域内的数据表示需要保留的数据,也就是在重置(reset 方法)buffer的时候,这部分数据是不会被删除的,强制要求保留。】
pos:
current position in the buffer, this is the index of the next character to be read from the buffer.
表示下一个即将读入的字符。
markpos:
The value of the pos field at the time the last mark method was called.
markpos 的数值等于上一次调用mark方法时候的pos位置。
1 public synchronized void mark(int readlimit) { 2 marklimit = readlimit; 3 markpos = pos; 4 }
count:
可以使用的buffer
二、fill()函数
当pos>count的时候,调用该方法来扩容。它总会将预留空间的位置挪动到buffer的前端。
1 private void fill() throws IOException { 2 byte[] buffer = getBufIfOpen(); 3 if (markpos < 0) 4 pos = 0; /* no mark: throw away the buffer */ 5 else if (pos >= buffer.length) /* no room left in buffer */ 6 if (markpos > 0) { /* can throw away early part of the buffer */ 7 int sz = pos - markpos; 8 System.arraycopy(buffer, markpos, buffer, 0, sz); 9 pos = sz; 10 markpos = 0; 11 } else if (buffer.length >= marklimit) { 12 markpos = -1; /* buffer got too big, invalidate mark */ 13 pos = 0; /* drop buffer contents */ 14 } else { /* grow buffer */ 15 int nsz = pos * 2; 16 if (nsz > marklimit) 17 nsz = marklimit; 18 byte nbuf[] = new byte[nsz]; 19 System.arraycopy(buffer, 0, nbuf, 0, pos); 20 if (!bufUpdater.compareAndSet(this, buffer, nbuf)) { 21 // Can't replace buf if there was an async close. 22 // Note: This would need to be changed if fill() 23 // is ever made accessible to multiple threads. 24 // But for now, the only way CAS can fail is via close. 25 // assert buf == null; 26 throw new IOException("Stream closed"); 27 } 28 buffer = nbuf; 29 } 30 count = pos; 31 int n = getInIfOpen().read(buffer, pos, buffer.length - pos); 32 if (n > 0) 33 count = n + pos; 34 }
byte[] buffer = getBufIfOpen(); 获取当前buffer的引用
if (markpos < 0)
pos = 0; /* no mark: throw away the buffer */ 整个buffer没有被标记过,也就是没有预留空间。
else if (pos >= buffer.length) /* no room left in buffer */ (markpos >0 或=0 )有预留空间,而且没有剩余空间可用。
if (markpos > 0) { /* can throw away early part of the buffer */ 预留空间的起始位置不在buffer的开始位置
int sz = pos - markpos; 挪动预留空间
System.arraycopy(buffer, markpos, buffer, 0, sz);
pos = sz;
markpos = 0;
} else if (buffer.length >= marklimit) { 如果marklimit的值小于缓存的长度,说明buffer很大,从内存使用的角度考虑,此时不宜再增大缓存的容量,
在这种情形下直接丢弃buf中的已有内容;
markpos = -1; /* buffer got too big, invalidate mark */
pos = 0; /* drop buffer contents */
} else { /* grow buffer */ 2倍扩展buffer
int nsz = pos * 2;
if (nsz > marklimit)
nsz = marklimit;
byte nbuf[] = new byte[nsz];
System.arraycopy(buffer, 0, nbuf, 0, pos);
if (!bufUpdater.compareAndSet(this, buffer, nbuf)) { 确保多线程情况下的可见性。
// Can't replace buf if there was an async close.
// Note: This would need to be changed if fill()
// is ever made accessible to multiple threads.
// But for now, the only way CAS can fail is via close.
// assert buf == null;
throw new IOException("Stream closed");
}
buffer = nbuf;
}