无效的BasicClientConnManager使用:连接仍然分配

我正在调用REST URL并尝试测量获取响应的时间。

我使用DefaultHttpClient来从REST URL获取响应。

在我的下面的程序中,每个线程将在一个特定的范围内工作。 像每个线程将在1 - 100之间工作,第二个线程将在101 - 200之间工作等

所以在我的下面的代码,第一次工作正常。 但是第二次,它是第二次在这一行httpclient.execute抛出exception,

 java.lang.IllegalStateException: Invalid use of BasicClientConnManager: connection still allocated. Make sure to release the connection before allocating another one. 

我在这里有什么错吗?

以下是我的代码 –

 class Task implements Runnable { private DefaultHttpClient httpclient = new DefaultHttpClient(); private HttpGet httpGet; private HttpResponse response; @Override public void run() { try { httpGet = new HttpGet( "http://localhost:8080/service/BEService/v1/get/USERID=10000/profile.ACCOUNT.SERVICE httpGet.getRequestLine(); for (int userId = id; userId < id + noOfTasks; userId++) { long start = System.nanoTime(); response = httpclient.execute(httpGet); long end = System.nanoTime() - start; } } catch (Exception e) { LOG.error("Threw a Exception in " + getClass().getSimpleName(), e); } } } 

更新的代码: –

如果我正在做这样的事情 –

 class Task implements Runnable { private DefaultHttpClient httpclient = new DefaultHttpClient(); private HttpGet httpGet; private HttpResponse response; @Override public void run() { try { for (int userId = id; userId < id + noOfTasks; userId++) { httpGet = new HttpGet("http://localhost:8080/service/BEService/v1/get/USERID=10000/profile.ACCOUNT.SERVICE"); httpGet.getRequestLine(); long start = System.nanoTime(); response = httpclient.execute(httpGet); long end = System.nanoTime() - start; HttpEntity entity = response.getEntity(); EntityUtils.consume(entity); } } catch (Exception e) { LOG.error("Threw a Exception in " + getClass().getSimpleName(), e); } } } 

那么它是好还是不好?

我在这里有什么错吗?

是。 如文件所述 :

BasicClientConnectionManager是一个简单的连接pipe理器,一次只能保持一个连接。 即使这个类是线程安全的,它也只能被一个执行线程使用。 BasicClientConnectionManager将努力重复使用相同路由的后续请求的连接。 但是,如果持续连接的路由与连接请求的路由不匹配,它将closures现有连接并重新打开给定路由。 如果连接已被分配,则引发java.lang.IllegalStateException。

BasicClientConnectionManager默认情况下由HttpClient使用。

请参阅“multithreading请求执行”了解如何使用可以跨多个线程处理请求的池化连接pipe理器 。

假设您使用的是默认的DefaultHttpClient (它在内部使用BasicClientConnectionManager ),您首先需要使用未完成/最后一个响应。

EntityUtils.consumeQuietly(httpResponse.getEntity());

否则,您可以每次重新分配DefaultHttpClient

来源: 解决方法不closuresDefaultHttpClient()每次使用后

这是我使用池连接pipe理器RestTemplate的configuration。 它在5个并发线程中运行得非常好。

 <!-- RestTemplate --> <beans:bean id="restTemplateYT" class="org.springframework.web.client.RestTemplate"> <beans:constructor-arg ref="httpRequestFactoryYT" /> </beans:bean> <beans:bean id="httpRequestFactoryYT" class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory"> <beans:constructor-arg> <beans:bean class="org.apache.http.impl.client.DefaultHttpClient"> <beans:constructor-arg> <beans:bean class="org.apache.http.impl.conn.PoolingClientConnectionManager"/> </beans:constructor-arg> </beans:bean> </beans:constructor-arg> <beans:property name="connectTimeout" value="5000" /> </beans:bean> 

spring的版本:3.1.0