我有一個應用程序有一個線程池(ThreadPoolExecutor)是交給任務,每個任務執行HttpGet操作並將InputStream讀入一個字節[]以執行某些操作。HttpClient內存管理
在閱讀了HttpClient文檔後,我發現管理多線程間HttpClient連接的最佳方式是創建一個ThreadSafeClientConnManager,並通過應用程序共享它。
執行此操作後,我注意到,即使完成所有任務後,ThreadSafeClientConnManager仍在使用大量內存。
查看堆轉儲,此內存是以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是非常準確基於從HttpClient examples爲Manual connection release的例子進行了Runnable。下面是它的一個例子:
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?
非常感謝。
我面臨類似問題的種類與HttpClient的4.3.6。我在每個請求完成後釋放連接,檢查陳舊連接,刪除空閒連接和過期連接,在讀取響應實體後關閉輸入流。但PoolingHttpclientConnectionManager仍然以某些會話輸入/輸出緩衝區的形式保存字節數組。你是如何解決這個問題的?任何幫助將不勝感激 – 2015-07-25 06:17:16