43

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

我正在使用DefaultHttpClient它来从REST URL.

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

所以在我下面的代码中,它第一次正常工作。但是第二次,它第二次在这条线上抛出异常,httpclient.execute因为-

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);
        }
    }
}

那么好还是不好?

4

3 回答 3

45

我在这里做错了什么吗?

是的。如文档中所述

BasicClientConnectionManager 是一个简单的连接管理器,一次只维护一个连接。即使这个类是线程安全的,它也应该只被一个执行线程使用。BasicClientConnectionManager 将努力为具有相同路由的后续请求重用连接。但是,如果持久连接的路由与连接请求的路由不匹配,它将关闭现有连接并为给定路由重新打开它。如果已分配连接,则抛出 java.lang.IllegalStateException。

HttpClient 默认使用 BasicClientConnectionManager。

有关如何使用可以跨多个线程处理请求的池连接管理器,请参阅“多线程请求执行” 。

于 2013-02-14T01:31:17.690 回答
43

假设您使用的是香草DefaultHttpClientBasicClientConnectionManager内部使用),您首先需要使用未完成/最后的响应。

EntityUtils.consumeQuietly(httpResponse.getEntity());

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

来源:每次使用后不关闭 DefaultHttpClient() 的解决方法

于 2013-04-25T09:56:48.933 回答
1

这是我使用池连接管理器对 RestTemplate 的配置。它在另外 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>

春季版:3.1.0

于 2014-03-12T08:16:59.530 回答