【安卓开发系列 -- APP 开源框架】IO 框架 OKIO

【1】OKIO的整体框架

【1.1】OKIO的整体框架图示

Android 开发相关源码精编解析下载 安卓app开源代码在哪下_java

Android 开发相关源码精编解析下载 安卓app开源代码在哪下_字符串_02

【1.2】OKIO的优势

CPU和内存消耗低,OKIO采用了segment机制进行内存共享和复用,尽可能少的申请内存,从而降低了GC的频率(过于频繁的GC会给应用程序带来性能问题);
使用方便,OKIO提供了ByteString来处理不变的byte序列,并在内存上做了优化,不管是从byte[]到String或是从String到byte[],操作便利,同时提供了如hex字符,base64等工具;提供了Buffer处理可变byte序列,可以根据使用情况自动增长,在使用过程中也不用去关心position等位置的处理;
N合一(OKIO精简了输入输出流的类个数),对于Java的原生IO,InputStream/OutputStream,若需要读取数据(如读取一个整数,一个布尔,或是一个浮点),需要用DataInputStream来包装;若作为缓存来使用,则需要使用BufferedOutputStream包装;OKIO提供的BufferedSink/BufferedSource具备以上功能,从而不需要再串联上一系列的装饰类;
提供了一系列的方便工具,如GZip的透明处理,对数据计算md5、sha1等的支持,使得数据校验方便;

详见,Android学习笔记——Okio

【2】OKIO使用方法示例

【2.1】OKIO示例代码

File inFile = new File(Environment.getExternalStorageDirectory() + "/" + "input.txt");
File outFile = new File(Environment.getExternalStorageDirectory() + "/" + "output.txt");
String name = "xiaoming";
int age = 11;
try {
    // 向文件写入数据
    Okio.buffer(Okio.sink(inFile)).writeUtf8(name).writeInt(age).close();
    // 拷贝文件
    Okio.buffer(Okio.sink(inFile)).writeAll(Okio.buffer(Okio.source(outFile)));
    // 从文件读取数据
    System.out.println(Okio.buffer(Okio.source(outFile)).readString(StandardCharsets.UTF_8));
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException ex) {
    ex.printStackTrace();
}

【2.2】OKIO读写流程图示

Android 开发相关源码精编解析下载 安卓app开源代码在哪下_Source_03

【3】OKIO源码分析

【3.1】Source/Sink接口

类继承结构图

Android 开发相关源码精编解析下载 安卓app开源代码在哪下_java_04

 Source接口源码

/**
 * Supplies a stream of bytes. Use this interface to read data from wherever
 * it's located: from the network, storage, or a buffer in memory. 
 *
 * 提供字节流,使用此接口可以从任何位置读取数据(网络、存储器或内存中的缓冲区)
 */
public interface Source extends Closeable {
  /**
   * Removes at least 1, and up to {@code byteCount} bytes from this and appends
   * them to {@code sink}. Returns the number of bytes read, or -1 if this
   * source is exhausted.
   *
   * 移除1至byteCount个字节并将这些字节追加到接收器(sink)
   * 返回读取的字节数,若source读取完毕则返回-1;
   */
  long read(Buffer sink, long byteCount) throws IOException;

  /** Returns the timeout for this source. */
  // 返回source的timeout值
  Timeout timeout();

  /**
   * Closes this source and releases the resources held by this source. It is an
   * error to read a closed source. It is safe to close a source more than once.
   *
   * 关闭此源并释放此源持有的资源
   * 读取关闭的源将产生错误
   * 源可以关闭多次
   */
  @Override void close() throws IOException;
}

/**
 * A source that keeps a buffer internally so that callers can do small reads without a performance
 * penalty. It also allows clients to read ahead, buffering as much as necessary before consuming
 * input.
 *
 * 一种在内部保留缓冲区的源,从而调用者可以在不影响性能的情况下进行小的读取
 * 还允许客户端进行预读,在使用输入之前尽可能多地进行缓冲
 */
public interface BufferedSource extends Source, ReadableByteChannel {
  /** Returns this source's internal buffer. */
  // 返回该source的内部buffer
  Buffer buffer();

  /**
   * Returns true if there are no more bytes in this source. This will block until there are bytes
   * to read or the source is definitely exhausted.
   *
   * 如果此源中没有更多的字节则返回true
   * 该方法将阻塞直到有字节可读取或源绝对耗尽
   */
  boolean exhausted() throws IOException;

  /**
   * Returns when the buffer contains at least {@code byteCount} bytes. Throws an
   * {@link java.io.EOFException} if the source is exhausted before the required bytes can be read.
   *
   * 当缓冲区至少包含byteCount个字节时返回
   * 若在读取所需字节之前源已用尽则抛出java.io.EOFException异常
   */
  void require(long byteCount) throws IOException;

  /**
   * Returns true when the buffer contains at least {@code byteCount} bytes, expanding it as
   * necessary. Returns false if the source is exhausted before the requested bytes can be read.
   *
   * 当缓冲区至少包含byteCount个字节时返回true,并根据需要对其进行扩展
   * 如果在读取请求的字节之前源已用尽则返回false
   */
  boolean request(long byteCount) throws IOException;

  /** Removes a byte from this source and returns it. */
  // 从源移除一个字节并返回该字节
  byte readByte() throws IOException;

  /**
   * Removes two bytes from this source and returns a big-endian short. <pre>{@code
   * 从源移除两个字节并返回一个大端的short变量
   */
  short readShort() throws IOException;

  /**
   * Removes two bytes from this source and returns a little-endian short. <pre>{@code
   * 从源移除两个字节并返回一个小端的short变量
   */
  short readShortLe() throws IOException;

  int readInt() throws IOException;

  int readIntLe() throws IOException;

  long readLong() throws IOException;

  long readLongLe() throws IOException;

  /**
   * Reads a long from this source in signed decimal form (i.e., as a string in base 10 with
   * optional leading '-')
   * 以带符号的十进制的形式从源中读取long变量
   */
  long readDecimalLong() throws IOException;

  /**
   * Reads a long form this source in hexadecimal form (i.e., as a string in base 16). This will
   * iterate until a non-hexadecimal character is found. <pre>{@code
   * 以十六进制形式从源中读取long变量
   * 该方法将迭代直到找到非十六进制字符
   */
  long readHexadecimalUnsignedLong() throws IOException;

  /**
   * Reads and discards {@code byteCount} bytes from this source. Throws an
   * {@link java.io.EOFException} if the source is exhausted before the
   * requested bytes can be skipped.
   * 从该源读取并丢弃byteCount字节
   * 如果在可以跳过请求的字节之前源已用尽则抛出java.io.EOFException
   */
  void skip(long byteCount) throws IOException;

  /** Removes all bytes bytes from this and returns them as a byte string. */
  // 从源中删除所有字节字节并作为字节字符串返回
  ByteString readByteString() throws IOException;

  /** Removes {@code byteCount} bytes from this and returns them as a byte string. */
  // 从源中删除byteCount个字节字节并作为字节字符串返回
  ByteString readByteString(long byteCount) throws IOException;

  /**
   * Finds the first string in {@code options} that is a prefix of this buffer, consumes it from
   * this buffer, and returns its index. If no byte string in {@code options} is a prefix of this
   * buffer this returns -1 and no bytes are consumed.
   * 在options中查找作为此缓冲区前缀的第一个字符串,从该缓冲区消费它并返回其索引
   */
  int select(Options options) throws IOException;

  /** Removes all bytes from this and returns them as a byte array. */
  // 从源中删除所有字节并作为字节数组返回
  byte[] readByteArray() throws IOException;

  /** Removes {@code byteCount} bytes from this and returns them as a byte array. */
  // 从中删除byteCount个字节并作为字节数组返回
  byte[] readByteArray(long byteCount) throws IOException;

  /**
   * Removes up to {@code sink.length} bytes from this and copies them into {@code sink}. Returns
   * the number of bytes read, or -1 if this source is exhausted.
   * 删除最多sink.length个字节并复制到sink
   */
  int read(byte[] sink) throws IOException;

  /**
   * Removes exactly {@code sink.length} bytes from this and copies them into {@code sink}. Throws
   * an {@link java.io.EOFException} if the requested number of bytes cannot be read.
   * 完全删除sink.length个字节并将其复制到sink
   * 如果无法读取需要的字节数则抛出java.io.EOFException异常
   */
  void readFully(byte[] sink) throws IOException;

  /**
   * Removes up to {@code byteCount} bytes from this and copies them into {@code sink} at {@code
   * offset}. Returns the number of bytes read, or -1 if this source is exhausted.
   * 从中删除最多byteCount个字节并复制到sink的offset处
   */
  int read(byte[] sink, int offset, int byteCount) throws IOException;

  /**
   * Removes exactly {@code byteCount} bytes from this and appends them to {@code sink}. Throws an
   * {@link java.io.EOFException} if the requested number of bytes cannot be read.
   * 删除byteCount个字节并附加到sink
   * 如果无法读取需要的字节数则抛出java.io.EOFException异常
   */
  void readFully(Buffer sink, long byteCount) throws IOException;

  /**
   * Removes all bytes from this and appends them to {@code sink}. Returns the total number of bytes
   * written to {@code sink} which will be 0 if this is exhausted.
   * 从中删除所有字节并附加到sink
   */
  long readAll(Sink sink) throws IOException;

  /**
   * Removes all bytes from this, decodes them as UTF-8, and returns the string. Returns the empty
   * string if this source is empty.
   * 从中删除所有字节解码为UTF-8并返回字符串;如果此源为空则返回空字符串;
   */
  String readUtf8() throws IOException;

  /**
   * Removes {@code byteCount} bytes from this, decodes them as UTF-8, and returns the string.
   * 从中删除byteCount个字节解码为UTF-8并返回字符串
   */
  String readUtf8(long byteCount) throws IOException;

  /**
   * Removes and returns characters up to but not including the next line break. A line break is
   * either {@code "\n"} or {@code "\r\n"}; these characters are not included in the result.
   * 删除并返回下一个换行符但不包括下一个换行符
   */
  @Nullable String readUtf8Line() throws IOException;

  /**
   * Removes and returns characters up to but not including the next line break. A line break is
   * either {@code "\n"} or {@code "\r\n"}; these characters are not included in the result.
   * 删除并返回下一个换行符但不包括下一个换行符
   */
  String readUtf8LineStrict() throws IOException;

  String readUtf8LineStrict(long limit) throws IOException;

  /**
   * Removes and returns a single UTF-8 code point, reading between 1 and 4 bytes as necessary.
   * 移除并传回单一的UTF-8码位,必要时读取1至4个位元组
   */
  int readUtf8CodePoint() throws IOException;

  /** Removes all bytes from this, decodes them as {@code charset}, and returns the string. */
  // 从中删除所有字节解码为charset并返回字符串
  String readString(Charset charset) throws IOException;

  String readString(long byteCount, Charset charset) throws IOException;

  long indexOf(byte b) throws IOException;

  /**
   * Returns the index of the first {@code b} in the buffer at or after {@code fromIndex}. This
   * expands the buffer as necessary until {@code b} is found. This reads an unbounded number of
   * bytes into the buffer. Returns -1 if the stream is exhausted before the requested byte is
   * found.
   * 返回缓冲区中位于fromindex处或之后的第一个b的索引
   */
  long indexOf(byte b, long fromIndex) throws IOException;

  long indexOf(byte b, long fromIndex, long toIndex) throws IOException;

  long indexOf(ByteString bytes) throws IOException;

  /**
   * Returns the index of the first match for {@code bytes} in the buffer at or after {@code
   * fromIndex}. This expands the buffer as necessary until {@code bytes} is found. This reads an
   * unbounded number of bytes into the buffer. Returns -1 if the stream is exhausted before the
   * requested bytes are found.
   * 返回缓冲区中bytes在codefromindex处或之后的第一个匹配项的索引
   */
  long indexOf(ByteString bytes, long fromIndex) throws IOException;

  long indexOfElement(ByteString targetBytes) throws IOException;

  /**
   * Returns the first index in this buffer that is at or after {@code fromIndex} and that contains
   * any of the bytes in {@code targetBytes}. This expands the buffer as necessary until a target
   * byte is found. This reads an unbounded number of bytes into the buffer. Returns -1 if the
   * stream is exhausted before the requested byte is found.
   * 返回此缓冲区中位于{@codefromindex}处或之后且包含{@code targetBytes}中任何字节的第一个索引
   */
  long indexOfElement(ByteString targetBytes, long fromIndex) throws IOException;

  /**
   * Returns true if the bytes at {@code offset} in this source equal {@code bytes}. This expands
   * the buffer as necessary until a byte does not match, all bytes are matched, or if the stream
   * is exhausted before enough bytes could determine a match.
   * 如果此源中offset处的字节等于bytes则返回true
   */
  boolean rangeEquals(long offset, ByteString bytes) throws IOException;

  /**
   * Returns true if {@code byteCount} bytes at {@code offset} in this source equal {@code bytes}
   * at {@code bytesOffset}. This expands the buffer as necessary until a byte does not match, all
   * bytes are matched, or if the stream is exhausted before enough bytes could determine a match.
   */
  boolean rangeEquals(long offset, ByteString bytes, int bytesOffset, int byteCount)
      throws IOException;

  /** Returns an input stream that reads from this source. */
  // 返回从source中读取的输入流
  InputStream inputStream();
}

Sink接口源码

/**
 * Receives a stream of bytes. Use this interface to write data wherever it's
 * needed: to the network, storage, or a buffer in memory. Sinks may be layered
 * to transform received data, such as to compress, encrypt, throttle, or add
 * protocol framing.
 *
 * 接收字节流
 * 使用此接口可以在需要的地方写入数据(网络、存储器或内存中的缓冲区)
 * 接收器可以分层以转换接收的数据,例如压缩、加密、调节或添加协议帧
 */
public interface Sink extends Closeable, Flushable {
  /** Removes {@code byteCount} bytes from {@code source} and appends them to this. */
  // 从source移除byteCount个字节并追加到sink中
  void write(Buffer source, long byteCount) throws IOException;

  /** Pushes all buffered bytes to their final destination. */
  // 将所有缓冲字节推送到最终目的地
  @Override void flush() throws IOException;

  /** Returns the timeout for this sink. */
  Timeout timeout();

  /**
   * Pushes all buffered bytes to their final destination and releases the
   * resources held by this sink. It is an error to write a closed sink. It is
   * safe to close a sink more than once.
   *
   * 将所有缓冲字节推送到最终目的地并释放此接收器保留的资源
   * 写已经关闭的sink将产生错误
   * 可以多次关闭一个sink
   */
  @Override void close() throws IOException;
}

/**
 * A sink that keeps a buffer internally so that callers can do small writes
 * without a performance penalty.
 *
 * 一种在内部保留缓冲区的接收器,从而调用者可以在不影响性能的情况下进行小的写入
 */
public interface BufferedSink extends Sink, WritableByteChannel {
  /** Returns this sink's internal buffer. */
  // 返回该sink的内部buffer
  Buffer buffer();
  // 写方法
  BufferedSink write(ByteString byteString) throws IOException;

  /**
   * 写入一个完整的字节数组
   */
  BufferedSink write(byte[] source) throws IOException;

  /**
   * 从字节数组源source的offset开始写入byteCount个字节
   */
  BufferedSink write(byte[] source, int offset, int byteCount) throws IOException;

  /**
   * 移除source中的所有字节并追加到sink中
   * 返回读取的字节数
   */
  long writeAll(Source source) throws IOException;

  // 移除source中的byteCount个字节并追加到sink中
  BufferedSink write(Source source, long byteCount) throws IOException;

  /**
   * 对string进行UTF-8编码并追加到sink中
   */
  BufferedSink writeUtf8(String string) throws IOException;

  /**
   * 对string字符串beginIndex到endIndex的字符进行UTF-8编码并追加到sink中
   */
  BufferedSink writeUtf8(String string, int beginIndex, int endIndex) throws IOException;

  /** Encodes {@code codePoint} in UTF-8 and writes it to this sink. */
  // 对int型数据进行UTF-8编码并追加到sink中
  BufferedSink writeUtf8CodePoint(int codePoint) throws IOException;

  /** Encodes {@code string} in {@code charset} and writes it to this sink. */
  // 对字符串进行指定类型的编码并追加到sink中
  BufferedSink writeString(String string, Charset charset) throws IOException;

  // 对字符串的beginIndex到endIndex进行指定类型的编码并追加到sink中
  BufferedSink writeString(String string, int beginIndex, int endIndex, Charset charset)
      throws IOException;

  /** Writes a byte to this sink. */
  // 写入一个字节到sink中
  BufferedSink writeByte(int b) throws IOException;
  // 使用两个字节向sink中写入大端short变量
  BufferedSink writeShort(int s) throws IOException;
  // 使用两个字节向sink中写入小端short变量
  BufferedSink writeShortLe(int s) throws IOException;

  BufferedSink writeInt(int i) throws IOException;

  BufferedSink writeIntLe(int i) throws IOException;

  BufferedSink writeLong(long v) throws IOException;

  BufferedSink writeLongLe(long v) throws IOException;
  /**
   * Writes a long to this sink in signed decimal form (i.e., as a string in base 10). <pre>{@code
   * 以带符号的十进制的形式向sink写入long变量
   */
  BufferedSink writeDecimalLong(long v) throws IOException;
  /**
   * Writes a long to this sink in hexadecimal form
   * 以十六进制形式向sink写入long变量
   */
  BufferedSink writeHexadecimalUnsignedLong(long v) throws IOException;

  /**
   * Writes all buffered data to the underlying sink, if one exists. Then that sink is recursively
   * flushed which pushes data as far as possible towards its ultimate destination. Typically that
   * destination is a network socket or file.
   *
   * 将所有缓冲数据写入基础接收器
   * 然后递归地刷新该接收器,从而将数据尽可能地推向最终目的地
   * 通常该目的地址是网络套接字或文件
   */
  @Override void flush() throws IOException;

  /**
   * Writes all buffered data to the underlying sink, if one exists. Like {@link #flush}, but
   * weaker. Call this before this buffered sink goes out of scope so that its data can reach its
   * destination. <pre>{@code
   *
   * 将所有缓冲数据写入基础接收器
   * 类似于flush方法但比较弱
   * 在该缓冲接收器超出作用域之前调用它,以便其数据可以到达目的地
   */
  BufferedSink emit() throws IOException;

  /**
   * Writes complete segments to the underlying sink, if one exists. Like {@link #flush}, but
   * weaker. Use this to limit the memory held in the buffer to a single segment. Typically
   * application code will not need to call this: it is only necessary when application code writes
   * directly to this {@linkplain #buffer() sink's buffer}. <pre>{@code
   *
   * 将完整段写入基础接收器
   * 类似于flush方法但比较弱
   * 使用该方法可将缓冲区中的内存限制为单个段
   * 通常,应用程序代码不需要调用这个函数:
   *    只有当应用程序代码直接写入该sink的buffer时才需要调用该方法
   */
  BufferedSink emitCompleteSegments() throws IOException;

  /** Returns an output stream that writes to this sink. */
  // 返回写入此接收器的输出流
  OutputStream outputStream();
}

【3.2】Buffer类

类继承结构图示

Android 开发相关源码精编解析下载 安卓app开源代码在哪下_字符串_05

Buffer类原理图示 

Android 开发相关源码精编解析下载 安卓app开源代码在哪下_字符串_06

Buffer源码分析

public final class Okio {

  // Returns a new source that buffers reads from {@code source}
  // 返回新的source,该源可以缓存从其中读取的数据
  public static BufferedSource buffer(Source source) {
    // RealBufferedSource类内部包含Buffer实例buffer
    // RealBufferedSource类中的read相关方法都转发给该Buffer实例buffer对应的read方法处理
    return new RealBufferedSource(source);
  }

  /** Returns a source that reads from {@code file}. */
  // 根据传入的File实例构建一个Source实例
  public static Source source(File file) throws FileNotFoundException {
    if (file == null) throw new IllegalArgumentException("file == null");
    return source(new FileInputStream(file));
  }

  /** Returns a source that reads from {@code in}. */
  // 根据InputStream实例构建一个Source实例
  public static Source source(InputStream in) {
    return source(in, new Timeout());
  }

  // 创建一个Source实例(带有超时)并实现接口中的方法
  private static Source source(final InputStream in, final Timeout timeout) {
    if (in == null) throw new IllegalArgumentException("in == null");
    if (timeout == null) throw new IllegalArgumentException("timeout == null");

    return new Source() {
      @Override public long read(Buffer sink, long byteCount) throws IOException {
        // 检查入参的有效性
        if (byteCount < 0) throw new IllegalArgumentException("byteCount < 0: " + byteCount);
        if (byteCount == 0) return 0;
        try {
          // 超时检查
          timeout.throwIfReached();
          // 获取一个可以写的Segment
        /**
         * Returns a tail segment that we can write at least minimumCapacity bytes to, creating it if necessary.
         * 返回tail指向的至少可以写入minimumCapacity容量字节Segment并且在必要时创建该Segment
         */
          Segment tail = sink.writableSegment(1);
          int maxToCopy = (int) Math.min(byteCount, Segment.SIZE - tail.limit);
          int bytesRead = in.read(tail.data, tail.limit, maxToCopy);
          if (bytesRead == -1) return -1;
          tail.limit += bytesRead;
          sink.size += bytesRead;
          return bytesRead;
        } catch (AssertionError e) {
          if (isAndroidGetsocknameError(e)) throw new IOException(e);
          throw e;
        }
      }

      // 关闭输出流
      @Override public void close() throws IOException {
        in.close();
      }

      // 返回Timeout实例
      @Override public Timeout timeout() {
        return timeout;
      }

      // 对象的toString方法覆写
      @Override public String toString() {
        return "source(" + in + ")";
      }
    };
  }  
}
public final class Okio {

  // Returns a new sink that buffers writes to {@code sink}
  // 返回新的sink,该sink可以缓存待写入其中的数据
  public static BufferedSink buffer(Sink sink) {
    // RealBufferedSource类内部包含Buffer实例buffer
    // RealBufferedSource类中的write相关方法都转发给该Buffer实例buffer对应的write方法处理 
    return new RealBufferedSink(sink);
  }

  /** Returns a sink that writes to {@code file}. */
  // 根据传入的File实例构建一个Sink实例
  public static Sink sink(File file) throws FileNotFoundException {
    if (file == null) throw new IllegalArgumentException("file == null");
    return sink(new FileOutputStream(file));
  }

  /** Returns a sink that writes to {@code out}. */
  // 根据OutputStream实例构建一个Sink实例
  public static Sink sink(OutputStream out) {
    return sink(out, new Timeout());
  }

  // 创建一个Sink实例(带有超时)并实现接口中的方法
  private static Sink sink(final OutputStream out, final Timeout timeout) {
    // 检查入参的有效性
    if (out == null) throw new IllegalArgumentException("out == null");
    if (timeout == null) throw new IllegalArgumentException("timeout == null");

    // 创建一个匿名Sink对象
    return new Sink() {
      // 覆写write方法
      @Override public void write(Buffer source, long byteCount) throws IOException {
        // 检查Buffer的有效性
        checkOffsetAndCount(source.size, 0, byteCount);
        // 循环读取数据
        while (byteCount > 0) {
          // 超时检查
          timeout.throwIfReached();
          Segment head = source.head;
          int toCopy = (int) Math.min(byteCount, head.limit - head.pos);
          out.write(head.data, head.pos, toCopy);

          head.pos += toCopy;
          byteCount -= toCopy;
          source.size -= toCopy;
          // 当一个Segment读取完毕则将该Segment放入SegmentPool中
          if (head.pos == head.limit) {
            // 源缓冲source双向Segment列表中弹出一个Segment
            source.head = head.pop();
            // SegmentPool回收弹出的Segment
            SegmentPool.recycle(head);
          }
        }
      }
      
      // 刷新输出流
      @Override public void flush() throws IOException {
        out.flush();
      }
      
      // 关闭输出流
      @Override public void close() throws IOException {
        out.close();
      }

      // 返回Timeout实例
      @Override public Timeout timeout() {
        return timeout;
      }
      
      // 对象的toString方法覆写
      @Override public String toString() {
        return "sink(" + out + ")";
      }
    };
  }
}

【3.3】Segment/SegmentPool

// A segment of a buffer
// 缓冲区中的一个分片
final class Segment {
  /** The size of all segments in bytes. */
  // 分片中的总字节数
  static final int SIZE = 8192;

  /** Segments will be shared when doing so avoids {@code arraycopy()} of this many bytes. */
  // 
  static final int SHARE_MINIMUM = 1024;

  // 存储数据
  final byte[] data;

  /** The next byte of application data byte to read in this segment. */
  // 下一次读取开始的位置
  int pos;

  /** The first byte of available data ready to be written to. */
  // 写入的开始位置
  int limit;

  /** True if other segments or byte strings use the same byte array. */
  // 若其他段或字节字符串使用相同的字节数组则取值为true
  boolean shared;

  /** True if this segment owns the byte array and can append to it, extending {@code limit}. */
  // 如果这个段拥有字节数组并且可以附加到该字节数组则取值为true
  // 标记data是否仅当前Segment独有
  boolean owner;

  /** Next segment in a linked or circularly-linked list. */
  // 循环双向链表的下一个节点
  Segment next;

  /** Previous segment in a circularly-linked list. */
  // 循环双向链表的前一个节点
  Segment prev;

  // Segment的构造方法
  // SegmentPool的take方法中调用
  Segment() {
    this.data = new byte[SIZE];
    this.owner = true;
    this.shared = false;
  }

  // Segment的构造方法
  // Segment类的sharedCopy/unsharedCopy以及SegmentedByteString类的write方法中调用
  Segment(byte[] data, int pos, int limit, boolean shared, boolean owner) {
    this.data = data;
    this.pos = pos;
    this.limit = limit;
    this.shared = shared;
    this.owner = owner;
  }

  /**
   * Returns a new segment that shares the underlying byte array with this. Adjusting pos and limit
   * are safe but writes are forbidden. This also marks the current segment as shared, which
   * prevents it from being pooled.
   *
   * 返回与该段共享字节数组的新段
   * 调整位置和限制是安全的但禁止写入
   * 将当前段标记为共享段并阻止该段被池化
   */
  Segment sharedCopy() {
    shared = true;
    return new Segment(data, pos, limit, true, false);
  }

  /** Returns a new segment that its own private copy of the underlying byte array. */
  // 返回一个新的段,该段拥有自己独有的底层字节数组
  Segment unsharedCopy() {
    return new Segment(data.clone(), pos, limit, false, true);
  }

  /**
   * Removes this segment of a circularly-linked list and returns its successor.
   * Returns null if the list is now empty.
   * 将当前段从循环链接列表中删除并返回其后续项
   * 如果当前列表为空则返回null
   */
  public @Nullable Segment pop() {
    Segment result = next != this ? next : null;
    prev.next = next;
    next.prev = prev;
    next = null;
    prev = null;
    return result;
  }

  /**
   * Appends {@code segment} after this segment in the circularly-linked list.
   * Returns the pushed segment.
   * 将入参segment追加到循环链接列表中的当前段之后
   * 返回加入的段
   */
  public Segment push(Segment segment) {
    segment.prev = this;
    segment.next = next;
    next.prev = segment;
    next = segment;
    return segment;
  }

  /**
   * Splits this head of a circularly-linked list into two segments. The first
   * segment contains the data in {@code [pos..pos+byteCount)}. The second
   * segment contains the data in {@code [pos+byteCount..limit)}. This can be
   * useful when moving partial segments from one buffer to another.
   * 将循环链表的头拆分为两段
   * 第一段包含{@code[pos..pos+byteCount)}中的数据
   * 第二段包含{@code [pos+byteCount..limit)}中的数据
   * 在将部分段从一个缓冲区移动到另一个缓冲区时非常有用
   */
  public Segment split(int byteCount) {
    if (byteCount <= 0 || byteCount > limit - pos) throw new IllegalArgumentException();
    Segment prefix;

    // We have two competing performance goals:
    //  - Avoid copying data. We accomplish this by sharing segments.
    //  - Avoid short shared segments. These are bad for performance because they are readonly and
    //    may lead to long chains of short segments.
    // To balance these goals we only share segments when the copy will be large.
    //
    // 性能处理
    // - 通过共享段避免拷贝数据
    // - 避免短的共享段,过短的段对性能不利,因为这些段是只读的并且这些短段会导致过长的链表
    // 在副本比较大的时候共享段以平衡上述的目标
    if (byteCount >= SHARE_MINIMUM) {
      prefix = sharedCopy();
    } else {
      prefix = SegmentPool.take();
      System.arraycopy(data, pos, prefix.data, 0, byteCount);
    }

    prefix.limit = prefix.pos + byteCount;
    pos += byteCount;
    prev.push(prefix);
    return prefix;
  }

  /**
   * Call this when the tail and its predecessor may both be less than half
   * full. This will copy data so that segments can be recycled.
   * 将当前Segment结点和prev前驱结点合并成一个Segment并统一合并到prev
   * 然后当前Segment结点从双向链表移除并添加到SegmentPool复用;
   *    合并的前提是,2个Segment的字节总和不超过8K,合并后可能会移动pos、limit
   */
  public void compact() {
    if (prev == this) throw new IllegalStateException();
    if (!prev.owner) return; // Cannot compact: prev isn't writable.
    int byteCount = limit - pos;
    int availableByteCount = SIZE - prev.limit + (prev.shared ? 0 : prev.pos);
    if (byteCount > availableByteCount) return; // Cannot compact: not enough writable space.
    writeTo(prev, byteCount);
    // 将当前段从循环链接列表中删除并返回其后续项
    pop();
    // 回收当前Segment到SegmentPool中
    SegmentPool.recycle(this);
  }

  /** Moves {@code byteCount} bytes from this segment to {@code sink}. */
  // 从当前节点移动byteCount个字节到{@code sink}中
  public void writeTo(Segment sink, int byteCount) {
    if (!sink.owner) throw new IllegalArgumentException();
    // sink中可写的空间不足
    if (sink.limit + byteCount > SIZE) {
      // We can't fit byteCount bytes at the sink's current position. Shift sink first.
      // 判断sink是否只读
      if (sink.shared) throw new IllegalArgumentException();
      // 判断sink中的剩余空间是否满足写入的字节数
      if (sink.limit + byteCount - sink.pos > SIZE) throw new IllegalArgumentException();
      // sink中的数据前移
      System.arraycopy(sink.data, sink.pos, sink.data, 0, sink.limit - sink.pos);
      sink.limit -= sink.pos;
      sink.pos = 0;
    }
    // 将当前Segment中的数据拷贝到sink中
    System.arraycopy(data, pos, sink.data, sink.limit, byteCount);
    sink.limit += byteCount;
    pos += byteCount;
  }
}
/**
 * A collection of unused segments, necessary to avoid GC churn and zero-fill.
 * This pool is a thread-safe static singleton.
 * 未使用段的集合,注意避免GC混乱和零填充
 * 此池是线程安全的静态单例
 */
final class SegmentPool {
  /** The maximum number of bytes to pool. */
  // 池的最大字节数
  static final long MAX_SIZE = 64 * 1024; // 64 KiB.

  /** Singly-linked list of segments. */
  // Segment的单向链列表
  static @Nullable Segment next;

  /** Total bytes in this pool. */
  // 此池中的总字节数
  static long byteCount;

  // SegmentPool的构造方法
  private SegmentPool() {
  }

  // 从池中获取一个Segment对象
  static Segment take() {
    synchronized (SegmentPool.class) {
      if (next != null) {
        Segment result = next;
        next = result.next;
        result.next = null;
        byteCount -= Segment.SIZE;
        return result;
      }
    }
    // 返回一个Segment实例,不要在持有锁的时候将Segment置零
    return new Segment(); // Pool is empty. Don't zero-fill while holding a lock.
  }

  // 将Segment状态初始化并回收到池中
  static void recycle(Segment segment) {
    if (segment.next != null || segment.prev != null) throw new IllegalArgumentException();
    // shared标记的Segment不能被回收
    if (segment.shared) return; // This segment cannot be recycled.
    synchronized (SegmentPool.class) {
      if (byteCount + Segment.SIZE > MAX_SIZE) return; // Pool is full.
      byteCount += Segment.SIZE;
      segment.next = next;
      segment.pos = segment.limit = 0;
      next = segment;
    }
  }
}

【3.4】Timeout机制

【3.4.1】Timeout类

// Timeout 类
public class Timeout {
  /**
   * An empty timeout that neither tracks nor detects timeouts. Use this when
   * timeouts aren't necessary, such as in implementations whose operations
   * do not block.
   * 空的Timeout实例,该实例既不跟踪也不检测超时
   * 通常在不需要超时时使用,比如非阻塞的操作
   */
  public static final Timeout NONE = new Timeout() {
    @Override public Timeout timeout(long timeout, TimeUnit unit) {
      return this;
    }

    @Override public Timeout deadlineNanoTime(long deadlineNanoTime) {
      return this;
    }

    @Override public void throwIfReached() throws IOException {
    }
  };

  /**
   * True if {@code deadlineNanoTime} is defined. There is no equivalent to null
   * or 0 for {@link System#nanoTime}.
   * 如果定义了{@code deadlineNanoTime}则为True
   */
  private boolean hasDeadline;
  // 截止时间点
  private long deadlineNanoTime;
  // timeout等待的时间
  private long timeoutNanos;

  public Timeout() {
  }

  /**
   * Wait at most {@code timeout} time before aborting an operation. Using a
   * per-operation timeout means that as long as forward progress is being made,
   * no sequence of operations will fail.
   * 在中止操作之前最多等待{@code timeout}
   * 对每个操作设置超时意味着,只要正在进行前向处理,任何操作序列都不会失败
   */
  public Timeout timeout(long timeout, TimeUnit unit) {
    if (timeout < 0) throw new IllegalArgumentException("timeout < 0: " + timeout);
    if (unit == null) throw new IllegalArgumentException("unit == null");
    this.timeoutNanos = unit.toNanos(timeout);
    return this;
  }

  /** Returns the timeout in nanoseconds, or {@code 0} for no timeout. */
  // 返回timeout时间大小
  public long timeoutNanos() {
    return timeoutNanos;
  }

  /** Returns true if a deadline is enabled. */
  // 返回是否使能了deadline
  public boolean hasDeadline() {
    return hasDeadline;
  }

  /**
   * Returns the {@linkplain System#nanoTime() nano time} when the deadline will
   * be reached.
   * 当到达deadline时间点时返回deadline的值
   */
  public long deadlineNanoTime() {
    if (!hasDeadline) throw new IllegalStateException("No deadline");
    return deadlineNanoTime;
  }

  /**
   * Sets the {@linkplain System#nanoTime() nano time} when the deadline will be
   * reached. All operations must complete before this time. Use a deadline to
   * set a maximum bound on the time spent on a sequence of operations.
   * 设置deadline
   * 在deadline之前所有的操作必须完成
   * 使用deadline设置操作序列所花费时间的最大限制
   */
  public Timeout deadlineNanoTime(long deadlineNanoTime) {
    this.hasDeadline = true;
    this.deadlineNanoTime = deadlineNanoTime;
    return this;
  }

  /** Set a deadline of now plus {@code duration} time. */
  // 设置deadline,按时间单位转换为纳秒
  public final Timeout deadline(long duration, TimeUnit unit) {
    if (duration <= 0) throw new IllegalArgumentException("duration <= 0: " + duration);
    if (unit == null) throw new IllegalArgumentException("unit == null");
    return deadlineNanoTime(System.nanoTime() + unit.toNanos(duration));
  }

  /** Clears the timeout. Operating system timeouts may still apply. */
  // 清除timeout,从而操作可以继续执行
  public Timeout clearTimeout() {
    this.timeoutNanos = 0;
    return this;
  }

  /** Clears the deadline. */
  // 关闭deadline
  public Timeout clearDeadline() {
    this.hasDeadline = false;
    return this;
  }

  /**
   * Throws an {@link InterruptedIOException} if the deadline has been reached or if the current
   * thread has been interrupted. This method doesn't detect timeouts; that should be implemented to
   * asynchronously abort an in-progress operation.
   * 当deadline到达并且当前线程中断后抛出InterruptedIOException异常
   * 此方法不检测超时,应实现超时以异步中止正在进行的操作
   */
  public void throwIfReached() throws IOException {
    if (Thread.interrupted()) {
      throw new InterruptedIOException("thread interrupted");
    }

    if (hasDeadline && deadlineNanoTime - System.nanoTime() <= 0) {
      throw new InterruptedIOException("deadline reached");
    }
  }

  /**
   * Waits on {@code monitor} until it is notified. Throws {@link InterruptedIOException} if either
   * the thread is interrupted or if this timeout elapses before {@code monitor} is notified. The
   * caller must be synchronized on {@code monitor}.
   * 在{@code monitor}等待直到接收到通知
   * 在线程中断或在{@code monitor}通知之前超时抛出InterruptedIOException异常
   * 调用者必须在{@code monitor}上同步
   */
  public final void waitUntilNotified(Object monitor) throws InterruptedIOException {
    try {
      boolean hasDeadline = hasDeadline();
      long timeoutNanos = timeoutNanos();

      if (!hasDeadline && timeoutNanos == 0L) {
        monitor.wait(); // There is no timeout: wait forever.
        return;
      }

      // Compute how long we'll wait.
      // 计算等待的时间
      long waitNanos;
      long start = System.nanoTime();
      if (hasDeadline && timeoutNanos != 0) {
        long deadlineNanos = deadlineNanoTime() - start;
        waitNanos = Math.min(timeoutNanos, deadlineNanos);
      } else if (hasDeadline) {
        waitNanos = deadlineNanoTime() - start;
      } else {
        waitNanos = timeoutNanos;
      }

      // Attempt to wait that long. This will break out early if the monitor is notified.
      long elapsedNanos = 0L;
      if (waitNanos > 0L) {
        long waitMillis = waitNanos / 1000000L;
        // 线程在监视器上等待一定的时间
        monitor.wait(waitMillis, (int) (waitNanos - waitMillis * 1000000L));
        elapsedNanos = System.nanoTime() - start;
      }

      // Throw if the timeout elapsed before the monitor was notified.
      // 若timeout在监视器的通知到达之前超过则抛出InterruptedIOException异常
      if (elapsedNanos >= waitNanos) {
        throw new InterruptedIOException("timeout");
      }
    } catch (InterruptedException e) {
      throw new InterruptedIOException("interrupted");
    }
  }
}

【3.4.2】AsyncTimeout类

// This timeout uses a background thread to take action exactly when the timeout occurs
// 此超时使用后台线程在超时发生时执行操作
public class AsyncTimeout extends Timeout {
  /**
   * Don't write more than 64 KiB of data at a time, give or take a segment. Otherwise slow
   * connections may suffer timeouts even when they're making (slow) progress. Without this, writing
   * a single 1 MiB buffer may never succeed on a sufficiently slow connection.
   * 一次写的数据不要超过64kb
   * 否则慢连接可能会出现超时,即使正在进行(缓慢)处理
   * 如果没有这一点则在一个足够慢的连接上写一个1MB缓冲区可能永远不会成功
   */
  private static final int TIMEOUT_WRITE_SIZE = 64 * 1024;

  /** Duration for the watchdog thread to be idle before it shuts itself down. */
  // 看门狗线程在关闭自身之前处于空闲状态的持续时间
  private static final long IDLE_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(60);
  private static final long IDLE_TIMEOUT_NANOS = TimeUnit.MILLISECONDS.toNanos(IDLE_TIMEOUT_MILLIS);

  /**
   * The watchdog thread processes a linked list of pending timeouts, sorted in the order to be
   * triggered. This class synchronizes on AsyncTimeout.class. This lock guards the queue.
   * 看门狗线程处理挂起超时的单向链表,timeout项按触发的顺序排序
   */
  static @Nullable AsyncTimeout head;

  /** True if this node is currently in the queue. */
  // 若当前节点在队列中则值为true
  private boolean inQueue;

  /** The next node in the linked list. */
  // 指向单向链表中的下一个节点
  private @Nullable AsyncTimeout next;

  /** If scheduled, this is the time that the watchdog should time this out. */
  // 超时时间
  private long timeoutAt;

  // 把当前AsyncTimeout对象加入节点并加入链表
  public final void enter() {
    // 检查参数
    if (inQueue) throw new IllegalStateException("Unbalanced enter/exit");
    long timeoutNanos = timeoutNanos();
    boolean hasDeadline = hasDeadline();
    if (timeoutNanos == 0 && !hasDeadline) {
      // 在没有deadline和timeout的情况下直接返回
      return; // No timeout and no deadline? Don't bother with the queue.
    }
    inQueue = true;
    // 节点入队并开启watchdog线程监视timeout链表
    scheduleTimeout(this, timeoutNanos, hasDeadline);
  }

  private static synchronized void scheduleTimeout(
      AsyncTimeout node, long timeoutNanos, boolean hasDeadline) {
    // Start the watchdog thread and create the head node when the first timeout is scheduled.
    // 若timeout链表为空则新建timeout链表并开始Watchdog线程
    if (head == null) {
      head = new AsyncTimeout();
      new Watchdog().start();
    }

    long now = System.nanoTime();
    // 确定当前节点的timeout时间点
    if (timeoutNanos != 0 && hasDeadline) {
      // Compute the earliest event; either timeout or deadline. Because nanoTime can wrap around,
      // Math.min() is undefined for absolute values, but meaningful for relative ones.
      node.timeoutAt = now + Math.min(timeoutNanos, node.deadlineNanoTime() - now);
    } else if (timeoutNanos != 0) {
      node.timeoutAt = now + timeoutNanos;
    } else if (hasDeadline) {
      node.timeoutAt = node.deadlineNanoTime();
    } else {
      throw new AssertionError();
    }

    // Insert the node in sorted order.
    // 计算到达timeout时间点剩余的时间
    long remainingNanos = node.remainingNanos(now);
    // 遍历timeout链表按照到达timeout的时间点的剩余时间排序
    for (AsyncTimeout prev = head; true; prev = prev.next) {
      if (prev.next == null || remainingNanos < prev.next.remainingNanos(now)) {
        node.next = prev.next;
        prev.next = node;
        if (prev == head) {
          // 插入节点之后唤醒watchdog线程
          AsyncTimeout.class.notify(); // Wake up the watchdog when inserting at the front.
        }
        break;
      }
    }
  }

  /** Returns true if the timeout occurred. */
  // 从链表中移除节点,若timeout发生则返回true
  public final boolean exit() {
    // 节点没有加入timeout链表则直接返回
    if (!inQueue) return false;
    inQueue = false;
    return cancelScheduledTimeout(this);
  }

  /** Returns true if the timeout occurred. */
  // 从链表中移除节点
  private static synchronized boolean cancelScheduledTimeout(AsyncTimeout node) {
    // Remove the node from the linked list.
    // 从链表中移除指定的节点
    for (AsyncTimeout prev = head; prev != null; prev = prev.next) {
      if (prev.next == node) {
        prev.next = node.next;
        node.next = null;
        return false;
      }
    }

    // The node wasn't found in the linked list: it must have timed out!
    // 若节点不在链表中则表明发生了timeout
    return true;
  }

  /**
   * 返回到达timeout时间点剩余的时间,该值可以为负,此时timeout立即发生
   */
  private long remainingNanos(long now) {
    return timeoutAt - now;
  }

  /**
   * 由watchdog线程在timeout发生时调用,处理timeout逻辑
   */
  protected void timedOut() {
  }

    ...

  /**
   * Throws an IOException if {@code throwOnTimeout} is {@code true} and a timeout occurred.
   * 如果{@code throwOnTimeout}为{@code true}并且发生超时则抛出IOException
   */
  final void exit(boolean throwOnTimeout) throws IOException {
    boolean timedOut = exit();
    if (timedOut && throwOnTimeout) throw newTimeoutException(null);
  }

  /**
   * Returns either {@code cause} or an IOException that's caused by {@code cause} if a timeout occurred.
   * 如果发生超时,则返回{@code cause}或由{@code cause}引起的IOException
   */
  final IOException exit(IOException cause) throws IOException {
    if (!exit()) return cause;
    return newTimeoutException(cause);
  }

  /**
   * Returns an {@link IOException} to represent a timeout.
   * 返回一个IOException异常表示timeout
   */
  protected IOException newTimeoutException(@Nullable IOException cause) {
    InterruptedIOException e = new InterruptedIOException("timeout");
    if (cause != null) {
      e.initCause(cause);
    }
    return e;
  }

  // Watchdog守护线程
  private static final class Watchdog extends Thread {
    Watchdog() {
      super("Okio Watchdog");
      setDaemon(true);
    }

    public void run() {
      while (true) {
        try {
          AsyncTimeout timedOut;
          synchronized (AsyncTimeout.class) {
            // awaitTimeout方法
            // 移除并返回位于链表顶部的节点,如有必要则等待其超时
            // 如果在启动时列表的头部没有节点并且在等待{@code IDLE_TIMEOUT_NANOS}之后仍然没有节点则返回{@link}head}
            // 如果在等待时插入了新节点则返回null
            // 否则,将返回正在等待且已删除的节点
            timedOut = awaitTimeout();

            // Didn't find a node to interrupt. Try again.
            // 返回null则表明链表中插入了新节点
            if (timedOut == null) continue;

            // The queue is completely empty. Let this thread exit and let another watchdog thread
            // get created on the next call to scheduleTimeout().
            // 返回head表明链表为空则退出当前Watchdog守护线程
            // 另一个Watchdog守护线程会在下一次调用scheduleTimeout()创建并启动
            if (timedOut == head) {
              head = null;
              return;
            }
          }

          // Close the timed out node.
          // 处理发生timeout的节点的timedOut()方法以实现特定的业务逻辑
          timedOut.timedOut();
        } catch (InterruptedException ignored) {
        }
      }
    }
  }

  /**
   * Removes and returns the node at the head of the list, waiting for it to time out if necessary.
   * 移除并返回位于链表顶部的节点,如有必要则等待其超时
   * 如果在启动时列表的头部没有节点并且在等待{@code IDLE_TIMEOUT_NANOS}之后仍然没有节点则返回{@link}head}
   * 如果在等待时插入了新节点则返回null
   * 否则,将返回正在等待且已删除的节点
   */
  static @Nullable AsyncTimeout awaitTimeout() throws InterruptedException {
    // Get the next eligible node.
    // 获取链表中的下一个节点
    AsyncTimeout node = head.next;

    // The queue is empty. Wait until either something is enqueued or the idle timeout elapses.
    // 若链表为空则等到新节点入队或timeout到达
    if (node == null) {
      long startNanos = System.nanoTime();
      AsyncTimeout.class.wait(IDLE_TIMEOUT_MILLIS);
      return head.next == null && (System.nanoTime() - startNanos) >= IDLE_TIMEOUT_NANOS
          ? head  // The idle timeout elapsed.
          : null; // The situation has changed.
    }

    long waitNanos = node.remainingNanos(System.nanoTime());
    // 链表的首节点没有timeout则等待
    // The head of the queue hasn't timed out yet. Await that.
    if (waitNanos > 0) {
      // Waiting is made complicated by the fact that we work in nanoseconds,
      // but the API wants (millis, nanos) in two arguments.
      long waitMillis = waitNanos / 1000000L;
      waitNanos -= (waitMillis * 1000000L);
      AsyncTimeout.class.wait(waitMillis, (int) waitNanos);
      return null;
    }

    // The head of the queue has timed out. Remove it.
    // 链表的首节点到达了timeout则首节点出队
    head.next = node.next;
    node.next = null;
    return node;
  }
}

【3.4.3】具有Timeout机制的Sink与Source

public class AsyncTimeout extends Timeout {

    ...

  /**
   * Returns a new sink that delegates to {@code sink}, using this to implement timeouts. This works
   * best if {@link #timedOut} is overridden to interrupt {@code sink}'s current operation.
   * 返回具有超时功能的Sink实例
   */
  public final Sink sink(final Sink sink) {
    return new Sink() {
      @Override public void write(Buffer source, long byteCount) throws IOException {
        checkOffsetAndCount(source.size, 0, byteCount);

        while (byteCount > 0L) {
          // Count how many bytes to write. This loop guarantees we split on a segment boundary.
          long toWrite = 0L;
          for (Segment s = source.head; toWrite < TIMEOUT_WRITE_SIZE; s = s.next) {
            int segmentSize = s.limit - s.pos;
            toWrite += segmentSize;
            if (toWrite >= byteCount) {
              toWrite = byteCount;
              break;
            }
          }

          // Emit one write. Only this section is subject to the timeout.
          boolean throwOnTimeout = false;
          enter();
          try {
            sink.write(source, toWrite);
            byteCount -= toWrite;
            throwOnTimeout = true;
          } catch (IOException e) {
            throw exit(e);
          } finally {
            exit(throwOnTimeout);
          }
        }
      }

      @Override public void flush() throws IOException {
        boolean throwOnTimeout = false;
        enter();
        try {
          sink.flush();
          throwOnTimeout = true;
        } catch (IOException e) {
          throw exit(e);
        } finally {
          exit(throwOnTimeout);
        }
      }

      @Override public void close() throws IOException {
        boolean throwOnTimeout = false;
        enter();
        try {
          sink.close();
          throwOnTimeout = true;
        } catch (IOException e) {
          throw exit(e);
        } finally {
          exit(throwOnTimeout);
        }
      }

      @Override public Timeout timeout() {
        return AsyncTimeout.this;
      }

      @Override public String toString() {
        return "AsyncTimeout.sink(" + sink + ")";
      }
    };
  }

  /**
   * Returns a new source that delegates to {@code source}, using this to implement timeouts. This
   * works best if {@link #timedOut} is overridden to interrupt {@code sink}'s current operation.
   * 返回具有超时功能的Source实例
   */
  public final Source source(final Source source) {
    return new Source() {
      @Override public long read(Buffer sink, long byteCount) throws IOException {
        boolean throwOnTimeout = false;
        enter();
        try {
          long result = source.read(sink, byteCount);
          throwOnTimeout = true;
          return result;
        } catch (IOException e) {
          throw exit(e);
        } finally {
          exit(throwOnTimeout);
        }
      }

      @Override public void close() throws IOException {
        boolean throwOnTimeout = false;
        try {
          source.close();
          throwOnTimeout = true;
        } catch (IOException e) {
          throw exit(e);
        } finally {
          exit(throwOnTimeout);
        }
      }

      @Override public Timeout timeout() {
        return AsyncTimeout.this;
      }

      @Override public String toString() {
        return "AsyncTimeout.source(" + source + ")";
      }
    };
  }

    ...

}

【3.5】生产者与消费者模型(Pipe)

public final class Pipe {
  // Pipe的最大容量
  final long maxBufferSize;
  // Buffer实例用于转发write/read方法
  final Buffer buffer = new Buffer();
  // 标记Sink是否关闭
  boolean sinkClosed;
  // 标记Source是否关闭
  boolean sourceClosed;
  // PipeSink实例,PipeSink为内部类
  private final Sink sink = new PipeSink();
  // PipeSource实例,PipeSource为内部类
  private final Source source = new PipeSource();
  // Pipe类的构造方法
  public Pipe(long maxBufferSize) {
    if (maxBufferSize < 1L) {
      throw new IllegalArgumentException("maxBufferSize < 1: " + maxBufferSize);
    }
    this.maxBufferSize = maxBufferSize;
  }
  // 返回PipeSource实例
  public Source source() {
    return source;
  }
  // 返回PipeSink实例
  public Sink sink() {
    return sink;
  }

  // PipeSink类实现了Sink接口并覆写了其中的方法
  final class PipeSink implements Sink {
    // 内部包含了Timeout实例
    final Timeout timeout = new Timeout();

    @Override public void write(Buffer source, long byteCount) throws IOException {
      synchronized (buffer) {
        if (sinkClosed) throw new IllegalStateException("closed");

        while (byteCount > 0) {
          if (sourceClosed) throw new IOException("source is closed");

          long bufferSpaceAvailable = maxBufferSize - buffer.size();
          if (bufferSpaceAvailable == 0) {
            // buffer中没有剩余空间等待消费者消费
            timeout.waitUntilNotified(buffer); // Wait until the source drains the buffer.
            continue;
          }

          long bytesToWrite = Math.min(bufferSpaceAvailable, byteCount);
          // 使用Buffer实例写入数据
          buffer.write(source, bytesToWrite);
          byteCount -= bytesToWrite;
          // 通知source有新的数据了
          buffer.notifyAll(); // Notify the source that it can resume reading.
        }
      }
    }

    @Override public void flush() throws IOException {
      synchronized (buffer) {
        if (sinkClosed) throw new IllegalStateException("closed");
        if (sourceClosed && buffer.size() > 0) throw new IOException("source is closed");
      }
    }

    @Override public void close() throws IOException {
      synchronized (buffer) {
        if (sinkClosed) return;
        if (sourceClosed && buffer.size() > 0) throw new IOException("source is closed");
        sinkClosed = true;
        // 通知source,此时没有新加入的数据了
        buffer.notifyAll(); // Notify the source that no more bytes are coming.
      }
    }

    @Override public Timeout timeout() {
      return timeout;
    }
  }

  // PipeSource类实现了Source接口并覆写了其中的方法
  final class PipeSource implements Source {
    final Timeout timeout = new Timeout();

    @Override public long read(Buffer sink, long byteCount) throws IOException {
      synchronized (buffer) {
        if (sourceClosed) throw new IllegalStateException("closed");

        while (buffer.size() == 0) {
          if (sinkClosed) return -1L;
          // Pipe中没有数据则等待生产者写入
          timeout.waitUntilNotified(buffer); // Wait until the sink fills the buffer.
        }

        long result = buffer.read(sink, byteCount);
        // 通知sink可以写入数据
        buffer.notifyAll(); // Notify the sink that it can resume writing.
        return result;
      }
    }

    @Override public void close() throws IOException {
      synchronized (buffer) {
        sourceClosed = true;
        // 通知sink,此时不再读取数据
        buffer.notifyAll(); // Notify the sink that no more bytes are desired.
      }
    }

    @Override public Timeout timeout() {
      return timeout;
    }
  }
}

参考致谢
本博客为博主的学习实践总结,并参考了众多博主的博文,在此表示感谢,博主若有不足之处,请批评指正。

【1】Android学习笔记——Okio

【2】拆轮子系列:拆 Okio