這篇文章概括了怎樣在多線程環(huán)境下安全的使用HttpClient。
建立連接
在HttpClient中使用多線程的一個(gè)主要原因是可以一次執(zhí)行多個(gè)方法。在執(zhí)行期間,每一個(gè)方法都使用一個(gè)HttpConnection實(shí)例。由于在同一時(shí)間多個(gè)連接只能安全地用于單一線程和方法和有限的資源,我們就必須確保連接分配給正確的方法。而MultiThreadedHttpConnectionManager完全可以代替我們完成這一項(xiàng)工作,這樣我們就不必去考慮多線程帶來安全的問題。MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); HttpClient client = new HttpClient(connectionManager);以上代碼中的HttpClient就在多線程中執(zhí)行多個(gè)方法了。當(dāng)我們?cè)俅握{(diào)用httpClient.executeMethod()方法時(shí),就會(huì)去Connection Manager中去請(qǐng)求HttpConneciton的實(shí)例,這樣就避免了線程安全問題,因?yàn)镠ttpClient已經(jīng)幫我們做了。
釋放連接
Connection Management比較重要的是當(dāng)連接不再使用時(shí),一定要手動(dòng)釋放。這樣做的原因是HttpClient不能夠確定哪個(gè)方法不被使用,哪個(gè)方法還在使用。這是因?yàn)镽esponse body不是由HttpClient來自動(dòng)讀取其數(shù)據(jù)的,而是由使用HttpClient的應(yīng)用程序來完成的。當(dāng)讀取Response的數(shù)據(jù)是時(shí),必須使用此方法的連接。這樣,在Response的數(shù)據(jù)在讀取前,HttpClient是沒有釋放連接的。所有這就要求在讀取完Response的數(shù)據(jù)后,應(yīng)用程序及時(shí)的使用releaseConnection()方法來釋放連接。特別注意,無論執(zhí)行的方法或是否也不例外被拋出。對(duì)于每一個(gè)HttpClient.executeMethod方法必須有一個(gè)method.releaseConnection ( )來釋放連接。
重用HttpClient實(shí)例
一般說來,建議一個(gè)通訊組件,甚至說一個(gè)應(yīng)用軟件就始終維持一個(gè)HttpClient對(duì)象實(shí)例存在。但是如果你的應(yīng)用很稀罕才用到它,而且還不允許這么一個(gè)實(shí)例一直存在,那么,這里強(qiáng)烈建議,一定要顯式地shut down 它的MultiThreadedHttpConnectionManager 。這樣做是確保連接池里的Connection得到釋放。
HttpMethod并發(fā)執(zhí)行
如果應(yīng)用程序邏輯允許并發(fā)執(zhí)行多個(gè)HTTP請(qǐng)求,(例如對(duì)多個(gè)服務(wù)器的多個(gè)并發(fā)請(qǐng)求,或?qū)ν粋€(gè)服務(wù)器代表不同用戶身份的多個(gè)請(qǐng)求) ,應(yīng)用程序可以為每一個(gè)HTTP session開啟一個(gè)專門的線程,這樣的設(shè)計(jì)自然將帶來顯著的性能提升。 而當(dāng)使用一個(gè)線程安全的連接管理器MultiThreadedHttpConnectionManager 時(shí),HttpClient能保證線程安全。這樣,多個(gè)線程可以共享這么一個(gè)線程安全的HttpClient實(shí)例。請(qǐng)注意,應(yīng)用程序的每個(gè)各自執(zhí)行的線程必須使用各自的HttpMethod實(shí)例;并且可配置各自的HttpState實(shí)例和/或HostConfiguration實(shí)例(代表一個(gè)特定的會(huì)話狀態(tài)和主機(jī)配置)。這個(gè)共享的HttpClient和其標(biāo)配的MultiThreadedHttpConnectionManager將為各線程帶來最高的性能。
使用流來發(fā)送和接收數(shù)據(jù)
HttpClient同時(shí)支持Stream和String/byte[]兩種方式來發(fā)送和接受數(shù)據(jù),但是由于String/byte[]的方式會(huì)造成內(nèi)存中有一份數(shù)據(jù)的拷貝或緩存,那么當(dāng)請(qǐng)求或應(yīng)答報(bào)文比較大,或者在高并發(fā)的應(yīng)用中,使用String/byte[]就會(huì)造成額外的內(nèi)存開銷,所以使用流的方式來傳輸數(shù)據(jù)是更好的選擇。
HttpClient的三種超時(shí)說明
/* 從連接池中取連接的超時(shí)時(shí)間 */ConnManagerParams.setTimeout(params, 1000);/* 連接超時(shí) */HttpConnectionParams.setConnectionTimeout(params, 2000);/* 請(qǐng)求超時(shí) */HttpConnectionParams.setSoTimeout(params, 4000); 第一行設(shè)置ConnectionPoolTimeout:這定義了從ConnectionManager管理的連接池中取出連接的超時(shí)時(shí)間,此處設(shè)置為1秒。第二行設(shè)置ConnectionTimeout: 這定義了通過網(wǎng)絡(luò)與服務(wù)器建立連接的超時(shí)時(shí)間。Httpclient包中通過一個(gè)異步線程去創(chuàng)建與服務(wù)器的socket連接,這就是該socket連接的超時(shí)時(shí)間,此處設(shè)置為2秒。第三行設(shè)置SocketTimeout: 這定義了Socket讀數(shù)據(jù)的超時(shí)時(shí)間,即從服務(wù)器獲取響應(yīng)數(shù)據(jù)需要等待的時(shí)間,此處設(shè)置為4秒。以上3種超時(shí)分別會(huì)拋出ConnectionPoolTimeoutException,ConnectionTimeoutException與SocketTimeoutException。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注