2012-08-14 23 views
4

與此問題密切相關:How to use HttpClient with multithreaded operation?,我在想如果apache HttpAsyncClient是線程安全的,或者它是否也需要使用MultiThreadedHttpConnectionManager或ThreadSafeClientConnManager。如何在多線程操作中使用HttpAsyncClient?

如果確實需要這樣的連接管理器,那麼存在於異步庫中嗎?

我能夠在異步庫中找到PoolingClientAsyncConnectionManager,但我不確定這是否是我需要的。

或者,我正在考慮使用ThreadLocal爲每個線程創建一個HttpAsyncClient對象。

請注意,與前面提到的問題不同,我需要狀態爲獨立跨會話,即使多個會話命中同一個域。如果在會話1中設置了cookie,則cookie應該會而不是對會話2可見。出於這個原因,我還考慮爲每個請求創建一個全新的HttpAsyncClient對象,儘管我得到的印象應該是更好的方法。

謝謝。

+0

當我想到更多關於它的,我不認爲ThreadLocal的正常工作。使用HttpClient,execute方法是阻塞的,但是對於HttpAsyncClient,execute方法是非阻塞的,所以單個線程可能會調用多次執行,這可能會導致與多個線程調用在同一個HttpClient對象上執行相同的干擾。 – Tinclon 2012-08-14 20:10:20

回答

1

負載既沒有在PoolingClientAsyncConnectionManager測試之後,我們發現,我們得到的結果不一致的時候,我們沒有使用PoolingClientAsyncConnectionManager。除此之外,我們還跟蹤了我們正在製作的Http調用的數量,以及已完成的Http調用的數量(通過取消(...),完成(...)或失敗(...)。 ..)相關的FutureCallback函數)。如果沒有PoolingClientAsyncConnectionManager,並且在負載較重的情況下,這兩個數字有時不匹配,導致我們認爲某處某些連接跺腳來自其他線程的連接信息(只是猜測)。

無論哪種方式,使用PoolingClientAsyncConnectionManager時,數字總是匹配的,負載測試都是成功的,所以我們肯定會使用它。

我們最終使用的代碼是這樣的:

public class RequestProcessor { 
    private RequestProcessor instance = new RequestProcessor(); 
    private PoolingClientAsyncConnectionManager pcm = null; 
    private HttpAsyncClient httpAsyncClient = null; 
    private RequestProcessor() { 
    // Initialize the PoolingClientAsyncConnectionManager, and the HttpAsyncClient 
    } 
    public void process(...) { 
    this.httpAsyncClient.execute(httpMethod, 
     new BasicHttpContext(), // Use a separate HttpContext for each request so information is not shared between requests 
     new FutureCallback<HttpResponse>() { 
     @Override 
     public void cancelled() { 
     // Do stuff 
     } 
     @Override 
     public void completed(HttpResponse httpResponse) { 
     // Do stuff 
     } 
     @Override 
     public void failed(Exception e) { 
     // Do stuff 
     } 
    }); 
    } 
} 
1

您提到「獨立會話」。如果這隻意味着cookies,那麼我會認爲創建自己的CookieStore,當你的每個線程去使用HttpClient就足夠了。

我會使用ThreadLocal創建一個線程客戶端,不要使用共享連接管理器,然後積極地清除cookie。這個答案是大約餅乾結算有用:

Android HttpClient persistent cookies

類似下面的代碼會工作。如果每個請求都是獨立的,我已經重寫了ThreadLocal.get()方法來調用clear()。您也可以在execute(...)方法中調用清除。

private static final ThreadLocal<ClientContext> localHttpContext = 
    new ThreadLocal<ClientContext>() { 
     @Override 
     protected ClientContext initialValue() { 
      return new ClientContext(); 
     } 
     @Override 
     public ClientContext get() { 
      ClientContext clientContext = super.get(); 
      // could do this to clear the context before usage by the thread 
      clientContext.clear(); 
      return clientContext; 
     } 
    }; 
... 

ClientContext clientContext = localHttpContext.get(); 
// if this wasn't in the get method above 
// clientContext.clear(); 
HttpGet httpGet = new HttpGet("http://www.google.com/"); 
HttpResponse response = clientContext.execute(httpGet); 
... 

private static class ClientContext { 
    final HttpClient httpClient = new DefaultHttpClient(); 
    final CookieStore cookieStore = new BasicCookieStore(); 
    final HttpContext localContext = new BasicHttpContext(); 
    public ClientContext() { 
     // bind cookie store to the local context 
     localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); 
    } 
    public HttpResponse execute(HttpUriRequest request) { 
     // in case you want each execute to be indepedent 
     // clientContext.clear(); 
     return httpClient.execute(request, httpContext); 
    } 
    public void clear() { 
     cookieStore.clear(); 
    } 
} 
+0

謝謝。這實際上看起來非常接近我已經得到的,除了清除cookie。 然而,cookie的事情只是一個例子。我的意思是我需要每個會議**完全**獨立於其他會議。在另一個會話中根本沒有數據可見。我需要擔心cookies嗎? – Tinclon 2012-08-14 19:44:48

+0

我這麼認爲@Tinclon。以下是一些文檔,當他們提到HttpClient狀態時,他們似乎只談論cookie:http://hc.apache.org/httpcomponents-client-ga/tutorial/html/statemgmt.html – Gray 2012-08-14 19:49:21

+0

認證信息是另一件需要擔心的事情@Tinclon但只有在您自己設置認證用戶名/密碼的情況下才有必要。 – Gray 2012-08-14 19:51:20