输入流上的所有数据都被消耗掉的那一刻,连接会自动释放并添加到连接池中。假设连接将在不久的将来被重用,底层的套接字连接没有被释放。在finally 块中调用disconnect 是一个好习惯,因为它会在exceptions 的情况下处理连接释放。
这里是FixedLengthInputStream的read方法的实现:
@Override public int read(byte[] buffer, int offset, int count) throws IOException {
Arrays.checkOffsetAndCount(buffer.length, offset, count);
checkNotClosed();
if (bytesRemaining == 0) {
return -1;
}
int read = in.read(buffer, offset, Math.min(count, bytesRemaining));
if (read == -1) {
unexpectedEndOfInput(); // the server didn't supply the promised content length
throw new IOException("unexpected end of stream");
}
bytesRemaining -= read;
cacheWrite(buffer, offset, read);
if (bytesRemaining == 0) {
endOfInput(true);
}
return read;
}
当 bytesRemaining 变量变为 0 时,endOfInput 被调用,这将进一步调用具有 true 参数的释放方法,这将确保连接被池化。
protected final void endOfInput(boolean reuseSocket) throws IOException {
if (cacheRequest != null) {
cacheBody.close();
}
httpEngine.release(reuseSocket);
}
这里是release 方法的实现。 最后的 if 检查确保连接是否需要关闭或添加到连接池以供重用。
public final void release(boolean reusable) {
// If the response body comes from the cache, close it.
if (responseBodyIn == cachedResponseBody) {
IoUtils.closeQuietly(responseBodyIn);
}
if (!connectionReleased && connection != null) {
connectionReleased = true;
// We cannot reuse sockets that have incomplete output.
if (requestBodyOut != null && !requestBodyOut.closed) {
reusable = false;
}
// If the headers specify that the connection shouldn't be reused, don't reuse it.
if (hasConnectionCloseHeader()) {
reusable = false;
}
if (responseBodyIn instanceof UnknownLengthHttpInputStream) {
reusable = false;
}
if (reusable && responseBodyIn != null) {
// We must discard the response body before the connection can be reused.
try {
Streams.skipAll(responseBodyIn);
} catch (IOException e) {
reusable = false;
}
}
if (!reusable) {
connection.closeSocketAndStreams();
connection = null;
} else if (automaticallyReleaseConnectionToPool) {
HttpConnectionPool.INSTANCE.recycle(connection);
connection = null;
}
}
}
注意:我之前回答了几个与 HttpURLConnection 相关的 SO 问题,这可以帮助您理解底层实现。以下是链接:Link1 和 Link2。