我使用的是Apache httpclient 4.3.4,我想在工作线程中重用httpclient实例,但是当httpclient在第二次发布数据时,该线程被阻塞了。
class SinglePostConnectionThread extends Thread {
void processResponse(CloseableHttpResponse response) throws Exception{
try{
StatusLine sLine = response.getStatusLine();
switch (sLine.getStatusCode()){
case 200:{
break;
}
case 204:{
//HttpEntity entity = response.getEntity();
//entity.getContent().close();
System.out.println("No Flight");
break;
}
default:
System.out.println("Bad response");
}
} catch (Exception e){
System.out.println(e.getMessage());
}finally {
System.out.println("Close response");
response.close();
}
}
@Override
public void run() {
BasicHttpClientConnectionManager basicConnManager = new BasicHttpClientConnectionManager();
HttpClientContext context = HttpClientContext.create();
try {
CloseableHttpClient client = HttpClients.custom().setConnectionManager(basicConnManager).build();
int tmpLoop = loopNum;
while (tmpLoop > 0) {
HttpPost post = new HttpPost(host);
StringEntity se = new StringEntity(toJson(bid), "utf-8");
post.setHeader(HTTP.CONTENT_TYPE, "application/json");
post.setEntity(se);
processResponse(client.execute(post, context));//blocked when running at second time
tmpLoop--;
if (loopNum ==0){
tmpLoop = 1;
}
post.releaseConnection();
//basicConnManager.;
}
} catch (Exception e){
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
似乎连接已用完,但实际上我关闭了所有资源。
您不能在多线程环境中使用简单连接管理器,即使此类是线程安全的,也应仅由一个执行线程使用。
2.3.2。简单的连接管理器
BasicHttpClientConnectionManager是一个简单的连接管理器,一次仅维护一个连接。即使此类是线程安全的,也应仅由一个执行线程使用。BasicHttpClientConnectionManager将努力对具有相同路由的后续请求重用该连接。但是,如果持久连接的路由与连接请求的路由不匹配,它将关闭现有连接并针对给定的路由重新打开它。如果已经分配了连接,则抛出java.lang.IllegalStateException。
因此,您已经使用了池连接管理器
2.3.3。池连接管理器
PoolingHttpClientConnectionManager是一个更复杂的实现,它管理客户端连接池,并且能够为来自多个执行线程的连接请求提供服务。连接是基于每个路由池的。通过在池中租用连接而不是创建全新的连接,可以为管理器在池中已经具有持久连接的路由请求提供服务。
PoolingHttpClientConnectionManager维护每个路由的总连接数上限。默认情况下,此实现将为每个给定路由创建不超过2个并发连接,并且总共不超过20个连接。对于许多现实应用程序,这些限制可能证明过于严格,特别是如果它们使用HTTP作为其服务的传输协议。
您可以看一下Threaded请求执行示例
package org.apache.http.examples.client;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
/**
* An example that performs GETs from multiple threads.
*
*/
public class ClientMultiThreadedExecution {
public static void main(String[] args) throws Exception {
// Create an HttpClient with the ThreadSafeClientConnManager.
// This connection manager must be used if more than one thread will
// be using the HttpClient.
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(100);
CloseableHttpClient httpclient = HttpClients.custom()
.setConnectionManager(cm)
.build();
try {
// create an array of URIs to perform GETs on
String[] urisToGet = {
"http://hc.apache.org/",
"http://hc.apache.org/httpcomponents-core-ga/",
"http://hc.apache.org/httpcomponents-client-ga/",
};
// create a thread for each URI
GetThread[] threads = new GetThread[urisToGet.length];
for (int i = 0; i < threads.length; i++) {
HttpGet httpget = new HttpGet(urisToGet[i]);
threads[i] = new GetThread(httpclient, httpget, i + 1);
}
// start the threads
for (int j = 0; j < threads.length; j++) {
threads[j].start();
}
// join the threads
for (int j = 0; j < threads.length; j++) {
threads[j].join();
}
} finally {
httpclient.close();
}
}
/**
* A thread that performs a GET.
*/
static class GetThread extends Thread {
private final CloseableHttpClient httpClient;
private final HttpContext context;
private final HttpGet httpget;
private final int id;
public GetThread(CloseableHttpClient httpClient, HttpGet httpget, int id) {
this.httpClient = httpClient;
this.context = new BasicHttpContext();
this.httpget = httpget;
this.id = id;
}
/**
* Executes the GetMethod and prints some status information.
*/
@Override
public void run() {
try {
System.out.println(id + " - about to get something from " + httpget.getURI());
CloseableHttpResponse response = httpClient.execute(httpget, context);
try {
System.out.println(id + " - get executed");
// get the response body as an array of bytes
HttpEntity entity = response.getEntity();
if (entity != null) {
byte[] bytes = EntityUtils.toByteArray(entity);
System.out.println(id + " - " + bytes.length + " bytes read");
}
} finally {
response.close();
}
} catch (Exception e) {
System.out.println(id + " - error: " + e);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5890 次 |
| 最近记录: |