本篇是为了解析IOUtils类的准备篇
1.
private void needNewBuffer(int newcount) {
if (currentBufferIndex < buffers.size() - 1) {
//Recycling old buffer
filledBufferSum += currentBuffer.length;
currentBufferIndex++;
currentBuffer = buffers.get(currentBufferIndex);
} else {
//Creating new buffer
int newBufferSize;
if (currentBuffer == null) {
newBufferSize = newcount;
filledBufferSum = 0;
} else {
newBufferSize = Math.max(
currentBuffer.length << 1,
newcount - filledBufferSum);
filledBufferSum += currentBuffer.length;
}
currentBufferIndex++;
currentBuffer = new byte[newBufferSize];
buffers.add(currentBuffer);
}
}
本函数用以创建一个新的buffer byte[] 单元。
假如还没用完已存在的buffer,就继续使用已存在的old buffer
假如已经用完(或还没有创建过):
1.没创建过,创建新的以newcount为length的byte[]
2.用完,创建新的byte[],但是这一部分有点疑问。为什么要选这个大小构建新的buffer byte[]
newBufferSize = Math.max(
currentBuffer.length << 1,
newcount - filledBufferSum);
注意:
这个方法在ByteArrayOutputStream(int size)这个构造函数中调用的时候,是使用
synchronized块包起来的,因为要避免不同线程下同时创建新的buffer
2.
public void write(byte[] b, int off, int len) {
if ((off < 0)
|| (off > b.length)
|| (len < 0)
|| ((off + len) > b.length)
|| ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return;
}
synchronized (this) {
int newcount = count + len;
int remaining = len;
int inBufferPos = count - filledBufferSum;
while (remaining > 0) {
int part = Math.min(remaining, currentBuffer.length - inBufferPos);
System.arraycopy(b, off + len - remaining, currentBuffer, inBufferPos, part);
remaining -= part;
if (remaining > 0) {
needNewBuffer(newcount);
inBufferPos = 0;
}
}
count = newcount;
}
}
同样是用synchronized块包住写入操作部分,这里运用一个remaining判断currentbuffer是否足以装下byte[],不足就继续needNewBuffer。
3.
/**
* Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in
* this class can be called after the stream has been closed without
* generating an <tt>IOException</tt>.
*
* @throws IOException never (this method should not declare this exception
* but it has to now due to backwards compatability)
*/
@Override
public void close() throws IOException {
//nop
}
特色是,无操作,因为对一个ByteArrayOutputStream进行close()操作没有任何效果,而且这样写不会产生重复关闭导致的Exception。
JDK 的 java.io.ByteArrayOutputStream里面也是这样做的
4.
public static InputStream toBufferedInputStream(InputStream input)
throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
output.write(input);
return output.toBufferedInputStream();
}
把一个inputstream取出返回一个新的完全内容一致的inputstream
使用情况:
- 源inputstream速度很慢
- 网络源,不能长时间保持打开
- 有网络时间限制
总结学习过程:
1.int c = Math.min(buf.length, remaining);
这行代码在我们写东西的时候,通过对比当前操作单位大小以及总操作剩余大小,起到自动选择写入大小的作用
2.synchronized语句的作用,当对类里面可能产生线程冲突操作的部分时,严格采用synchronized语句,一个类同时只允许一个获得了syncObject的线程执行一个synchronized方法/块
Synchronized理解:(摘自baidu百科)
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
三、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的除synchronized(this)同步代码块以外的部分。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用