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位置。
public synchronized void mark(int readlimit) {
marklimit = readlimit;
markpos = pos;
}
count:
可以使用的buffer
二、fill()函数
当pos>count的时候,调用该方法来扩容。它总会将预留空间的位置挪动到buffer的前端。
private void fill() throws IOException {
byte[] buffer = getBufIfOpen();
if (markpos < 0)
pos = 0; /* no mark: throw away the buffer */
else if (pos >= buffer.length) /* no room left in buffer */
if (markpos > 0) { /* can throw away early part of the buffer */
int sz = pos - markpos;
System.arraycopy(buffer, markpos, buffer, 0, sz);
pos = sz;
markpos = 0;
} else if (buffer.length >= marklimit) {
markpos = -1; /* buffer got too big, invalidate mark */
pos = 0; /* drop buffer contents */
} else { /* grow 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;
}
count = pos;
int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
if (n > 0)
count = n + pos;
}
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;
}

BufferedInputStream 源码分析的更多相关文章
- java.io.BufferedInputStream 源码分析
BufferedInputStream是一个带缓冲区的输入流,在读取字节数据时可以从底层流中一次性读取多个字节到缓冲区,而不必每次读取操作都调用底层流,从而提高系统性能. 先介绍几个关键属性 //默认 ...
- 【Zookeeper】源码分析之持久化--FileSnap
一.前言 前篇博文已经分析了FileTxnLog的源码,现在接着分析持久化中的FileSnap,其主要提供了快照相应的接口. 二.SnapShot源码分析 SnapShot是FileTxnLog的父类 ...
- 【Zookeeper】源码分析之持久化(二)之FileSnap
一.前言 前篇博文已经分析了FileTxnLog的源码,现在接着分析持久化中的FileSnap,其主要提供了快照相应的接口. 二.SnapShot源码分析 SnapShot是FileTxnLog的父类 ...
- hadoop的RPC机制 -源码分析
这些天一直奔波于长沙和武汉之间,忙着腾讯的笔试.面试,以至于对hadoop RPC(Remote Procedure Call Protocol ,远程过程调用协议,它是一种通过网络从远程计算机程序上 ...
- Spark大师之路:广播变量(Broadcast)源码分析
概述 最近工作上忙死了……广播变量这一块其实早就看过了,一直没有贴出来. 本文基于Spark 1.0源码分析,主要探讨广播变量的初始化.创建.读取以及清除. 类关系 BroadcastManager类 ...
- TOMCAT8源码分析——SESSION管理分析(上)
前言 对于广大java开发者而已,对于J2EE规范中的Session应该并不陌生,我们可以使用Session管理用户的会话信息,最常见的就是拿Session用来存放用户登录.身份.权限及状态等信息.对 ...
- Tomcat源码分析——Session管理分析(上)
前言 对于广大java开发者而已,对于J2EE规范中的Session应该并不陌生,我们可以使用Session管理用户的会话信息,最常见的就是拿Session用来存放用户登录.身份.权限及状态等信息.对 ...
- Hadoop的RPC机制源码分析
分析对象: hadoop版本:hadoop 0.20.203.0 必备技术点: 1. 动态代理(参考 :http://www.cnblogs.com/sh425/p/6893662.html )2. ...
- HDFS源码分析DataXceiver之整体流程
在<HDFS源码分析之DataXceiverServer>一文中,我们了解到在DataNode中,有一个后台工作的线程DataXceiverServer.它被用于接收来自客户端或其他数据节 ...
随机推荐
- Latex调整行距
修改行间距的方法: \usepackage{setspace}%使用间距宏包 \begin{document} \begin{spacing}{2.0}%%行间距变为double-space 双倍行距 ...
- lambda, reduce, map求阶乘之和
学完这几个优雅的内建函数,就可以做一些有趣的小练习来激发兴趣了.而python最大的好处便是简洁,看下边要求 用1行代码求 1! + 2! + 3! + ... + 10! 求阶乘 reduce函数用 ...
- Linux中fork()函数详解(转载)
[原创地址]http://blog.csdn.net/jason314/article/details/5640969 [转载地址]http://www.cnblogs.com/bastard/arc ...
- 非常可乐(bfs)
非常可乐 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
- 【iOS知识学习】_UITableView简介
UITableView在iOS中估计是用的最多的控件了吧,几乎每个app都会用到. 一.它是一个非常重要的类来在table中展示数据. 1.是一个一维的表: 2.是UIScrollView的一个子类: ...
- c#Winform程序的toolStripButton自己定义背景应用演示样例源代码
C# Winform程序的toolStrip中toolStripButton的背景是蓝色的,怎样改变背景及边框的颜色和样式呢? 实现此功能须要重写toolStripButton的Paint方法 这里仅 ...
- centos 安装 erlang
1.首先下载erlang 安装源文件 可以在官网上下载 : http://www.erlang.org/ 官网上提供多个版本: 2.下载完成后将R16B01 Source File对应的 ot ...
- ajax不执行success回调而是执行了error回调
最近在看jQuery的API文档,在使用到jQuery的ajax时,如果指定了dataType为json,老是不执行success回调,而是执行了error回调函数. 附上代码如下: JScrip ...
- Android中的一些基础知识(二)
这几天在回顾Android的基础知识,就把一些常见的知识点整理一下,以后忘了也可以翻出来看一看. 简单介绍一下Activity的生命周期 在API文档中对生命周期回调的函数描述的很详细,这里我只是翻译 ...
- for语句及switch case用法示例
for(初始条件:循环条件:状态改变){ 循环体:执行代码} 示例一: 示例二: 示例三: 示例四: 示例五: 示例六: 示例七: switch case: 示例一: 示例二: 示例三: