更新int count变量,fill()函数中getInIfOpen().read(buffer, pos, buffer.length - pos)这行代码的返回值为8192,

📅 2026/6/30 2:00:30
更新int count变量,fill()函数中getInIfOpen().read(buffer, pos, buffer.length - pos)这行代码的返回值为8192,
执行getBufIfOpen()[pos] 0xff从缓冲区byte[]数组中获取第pos此时pos0个索引位置的字节返回给BufferedInputStream.class::read()函数的调用方并更新pos的值为pos1之后每次调用BufferedInputStream.class::read()函数时都不会再执行fill()函数了并且当pos4096时执行了bis.mark(8192)设置marklimit8192markpospos4096。直到pos8192时执行BufferedInputStream.class::read()函数才会再次执行fill()函数本次填充缓冲区byte[]数组的过程如下①、执行fill()函数的如下代码片段标题3.1.4也会复用之后的逻辑...省略部分代码... else if (pos buffer.length) if (markpos 0) { //场景一pos缓冲区byte[]数组的长度并且markpos 0 int sz pos - markpos; //只把缓冲区byte[]数组中[markpos,pos) 索引区间的元素复制到缓冲区byte[]数组[0,pos-markpos索引区间 System.arraycopy(buffer, markpos, buffer, 0, sz); pos sz;//设置pospos-markpos markpos 0;//设置markpos0 } ...省略部分代码...先把缓冲区byte[]数组中[4096,8192) 索引区间的元素复制到缓冲区byte[]数组[0,4096索引区间如下所示再更新pos4096markpos 0②、然后从被装饰的输入StreamFileInputStream读取第8193~12286个字节到缓冲区byte[]数组的[4096,8192)索引位置左闭右开不包括byte[]数组的第8192个索引位置并返回读取的字节数量。如下所示然后更新count此时count n pos409640968192pos4096markpos 0③、执行getBufIfOpen()[pos] 0xff从缓冲区byte[]数组中获取第pos此时pos4096个索引位置的字节返回给BufferedInputStream.class::read()函数的调用方并更新pos的值为pos1之后每次调用BufferedInputStream.class::read()函数时都不会再执行fill()函数了直到pos8192时此时count 8192markpos0执行BufferedInputStream.class::read()函数才会再次执行fill()函数后续过程分为以下2种情景情景一如上伪代码bis.mark(8192)设置marklimit8192缓冲区byte[]数组的长度①、执行fill()函数的如下代码片段...省略部分代码... } else if (buffer.length marklimit) {//场景二pos缓冲区byte[]数组的长度并且缓冲区byte[]数组的长度 marklimit markpos -1; //设置markpos -1 pos 0; //设置pos 0 } ...省略部分代码...先更新pos 0markpos -1然后从被装饰的输入StreamFileInputStream读取第12287~20000个字节到缓冲区byte[]数组的[0,7914)索引位置左闭右开不包括byte[]数组的第7914个索引位置并返回读取的字节数量。如下所示此时被装饰的输入StreamFileInputStream中的字节被全部读取完毕被装饰的输入StreamFileInputStream为空。②、更新int count变量fill()函数中getInIfOpen().read(buffer, pos, buffer.length - pos)这行代码的返回值为7914count791407914③、执行getBufIfOpen()[pos] 0xff从缓冲区byte[]数组中获取第pos此时pos0个索引位置的字节返回给BufferedInputStream.class::read()函数的调用方并更新pos的值为pos1之后每次调用BufferedInputStream.class::read()函数时都不会再执行fill()函数了直到pos7914时执行BufferedInputStream.class::read()函数才会再次执行fill()函数过程如下①、因为markpos -1所以更新pos0count0缓冲区byte[]数组中的数据如下此时由于被装饰的输入StreamFileInputStream中的字节被全部读取完毕fill()函数中getInIfOpen().read(buffer, pos, buffer.length - pos)这行代码的返回值为0无法更新count结束fill()函数的调用②、执行return -1返回给BufferedInputStream.class::read()函数的调用方情景二改变上面的伪代码bis.mark(8192)而是设置marklimit缓冲区byte[]数组的长度只要是大于8192的任何值都可以比如bis.mark(16384)①、执行fill()函数的如下代码片段...省略部分代码... } else {//场景四pos缓冲区byte[]数组的长度并且不满足场景一、二、三时将缓冲区byte[]数组扩容 //如果pos2147483639/2则新缓冲区byte[]数组的长度nszpos*2否则新缓冲区byte[]数组的长度nsz2147483639 int nsz (pos MAX_BUFFER_SIZE - pos) ? pos * 2 : MAX_BUFFER_SIZE; if (nsz marklimit) nsz marklimit;//当新缓冲区byte[]数组的长度nszmarklimit新缓冲区byte[]数组的长度nszmarklimit byte nbuf[] new byte[nsz];//新建一个新缓冲区byte[]数组 System.arraycopy(buffer, 0, nbuf, 0, pos);//将老缓冲区byte[]数组中[0,pos)索引区间的元素复制到新缓冲区byte[]数组[0,pos)索引区间 if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {//通过CASCompare-And-Swap操作来原子地更新buf变量 // Cant 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;//新缓冲区byte[]数组创建完毕 } ...省略部分代码...先扩大缓冲区byte[]数组的长度到16384扩大前缓冲区长度为8192然后将旧缓冲区byte[]数组中的内容移动到新缓冲区byte[]数组对应的索引位置上如下所示然后通过CASCompare-And-Swap操作来原子地更新buf变量的引用。②、然后从被装饰的输入StreamFileInputStream读取第12287~20000个字节到新缓冲区byte[]数组的[8192,16106)索引位置左闭右开不包括新byte[]数组的第16106个索引位置并返回读取的字节数量。如下所示此时被装饰的输入StreamFileInputStream中的字节被全部读取完毕被装饰的输入StreamFileInputStream为空。③、更新int count变量fill()函数中getInIfOpen().read(buffer, pos, buffer.length - pos)这行代码的返回值为7914count7914pos16106④、执行getBufIfOpen()[pos] 0xff从缓冲区byte[]数组中获取第pos此时pos8192个索引位置的字节返回给BufferedInputStream.class::read()函数的调用方并更新pos的值为pos1之后每次调用BufferedInputStream.class::read()函数时都不会再执行fill()函数了直到pos16106时执行BufferedInputStream.class::read()函数才会再次执行fill()函数过程如下①、因为markpos 0不会设置pos0也不会再执行场景一、场景二、场景三、场景四标题三源码中的注释、新缓冲区byte[]数组中的数据如下此时由于被装饰的输入StreamFileInputStream中的字节被全部读取完毕fill()函数中getInIfOpen().read(buffer, pos, buffer.length - pos)这行代码的返回值为0无法更新count变量结束fill()函数的调用②、执行return -1返回给BufferedInputStream.class::read()函数的调用方3.1.3、如果在多次执行BufferedInputStream.class::read()函数之后执行过mark()函数如果在很多次调用read()函数之中调用了mark(8192)函数如下伪代码InputStream is new FileInputStream(D:\\nio-data.txt); BufferedInputStream bis new BufferedInputStream(is); int bytesRead; while ((bytesRead bis.read()) ! -1) { //处理读取到的字节bytesRead } bis.mark(8192);//设置marklimit8192markpospos0那么BufferedInputStream对象中的缓冲区byte[]数组的长度为8192缓存8KB字节上述代码的执行过程如下假设被装饰的输入StreamFileInputStream中有10000个字节参考标题3.1与标题3.1不同的是最后执行bis.mark(8192);设置marklimit8192markpospos0。3.1.4、如果在多次执行BufferedInputStream.class::read()函数之中执行过mark()函数和reset()函数如果在很多次调用read()函数之中调用了mark(8192)函数然后又调用了reset()函数如下伪代码InputStream is new FileInputStream(D:\\nio-data.txt);//假设该被装饰的输入StreamFileInputStream中有20000个字节 BufferedInputStream bis new BufferedInputStream(is); int bytesRead; int i 0; while ((bytesRead bis.read()) ! -1) { if(i4096){ bis.mark(8192);//设置marklimit8192markpospos4096 } //处理读取到的字节bytesRead if(i8196){ bis.reset();//当pos8196时执行reset()函数设置posmarkpos0 } }那么BufferedInputStream对象中的缓冲区byte[]数组的长度为8192缓存8KB字节上述代码的执行过程如下假设被装饰的输入StreamFileInputStream中有20000个字节①、poscount0缓冲区byte[]数组中还没有填充任何数据执行fill()函数然后将被装饰的输入StreamFileInputStream中的字节读取到缓冲区byte[]数组的[0,8192)索引位置左闭右开不包括byte[]数组的第8192个索引位置并返回读取的字节数量。如下所示