无效的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