gpt4 book ai didi

java - HttpClient内存管理

转载 作者:搜寻专家 更新时间:2023-10-30 19:43:53 24 4
gpt4 key购买 nike

我有一个具有线程池 (ThreadPoolExecutor) 的应用程序,该线程池负责处理每个执行 HttpGet 操作并将 InputStream 读入 byte[] 以执行某些操作的任务。

阅读 HttpClient 文档后,我的印象是管理跨多个线程的 HttpClient 连接的最佳方法是创建一个 ThreadSafeClientConnManager 并在整个应用程序中共享它。

实现此操作后,我注意到即使所有任务都已完成,ThreadSafeClientConnManager 仍在使用大量内存。

查看heap dump,这 block 内存是byte[]数组的形式。这些不被我创建的任何引用所持有。它们由 ThreadSafeClientConnManager 及其池的一部分持有。我不确定它们是与 InputStreams 相关还是其他。

所有任务本身及其变量都已成功进行垃圾回收。

如果我在 ThreadSafeClientConnManager 上调用 getConnectionManager().shutdown(),那么所有内存都会被释放。但是,我不想关闭连接,因为这些 HttpGet 任务可能随时发生。我想在应用程序生命周期内让它保持打开状态。

随着 HttpGet 任务的运行,占用的内存会越来越多,最终会导致内存不足错误。当任务完成时,内存不会被释放。

如何确保在使用它的任务完成后释放内存?

这是我使用的代码。它与我从 HttpClient 文档编写的代码一样拼凑在一起,其他问题在 SO 和在线上。

HttpClient 的创建:

// Create and initialize HTTP parameters
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, 40 * 1000);
HttpConnectionParams.setSoTimeout(params, 40 * 1000);
ConnManagerParams.setMaxTotalConnections(params, 100);
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);

// Create and initialize scheme registry
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register( new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));

// Create an HttpClient with the ThreadSafeClientConnManager.
// This connection manager must be used if more than one thread will
// be using the HttpClient.
ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
mHttpClient = new DefaultHttpClient(cm, params);

然后,执行 HttpGet 的 Runnable 几乎完全基于 HttpClient examples 中的示例。对于Manual connection release .这是它的外观示例:

HttpClient httpclient = getTheSharedThreadSafeClientConnManager(); // Would return the mHttpClient from above
try {
HttpGet httpget = new HttpGet("http://www.apache.org/");

// Execute HTTP request
System.out.println("executing request " + httpget.getURI());
HttpResponse response = httpclient.execute(httpget);

System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
System.out.println("----------------------------------------");

// Get hold of the response entity
HttpEntity entity = response.getEntity();

// If the response does not enclose an entity, there is no need
// to bother about connection release
if (entity != null) {
InputStream instream = entity.getContent();
try {
instream.read();
// do something useful with the response
} catch (IOException ex) {
// In case of an IOException the connection will be released
// back to the connection manager automatically
throw ex;
} catch (RuntimeException ex) {
// In case of an unexpected exception you may want to abort
// the HTTP request in order to shut down the underlying
// connection immediately.
httpget.abort();
throw ex;
} finally {
// Closing the input stream will trigger connection release
try { instream.close(); } catch (Exception ignore) {}
}
}

}

为了释放每个任务的资源,您还需要做更多的事情吗?我在他们的 ThreadSafeClientConnManager 示例中看到他们使用了 HttpContext,但我找不到任何关于如何使用它的文档。那是必需的吗?如果是这样,您如何将它与 ThreadPoolExecutor 一起使用?

非常感谢。

最佳答案

您是否调用过 ClientConnectionManager 的 releaseConnection(...) 或 closeExpiredConnections() 方法?

关于java - HttpClient内存管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4999708/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com