基本客户端管理程序的使用无效:连接仍已分配

2022-09-01 00:26:50

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

我正在使用它来获取来自的响应。DefaultHttpClientREST URL

在我下面的程序中,每个线程将在一个特定的范围内工作。就像每个线程将在之间工作,第二个线程将在等之间工作。1 - 100101 - 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);
        }
    }
}

那就好不好吗?


答案 1

我在这里做错了什么吗?

是的。如文档中所述:

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

BasicClientConnectionManager由HttpClient默认使用。

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


答案 2

假设您正在使用vanilla(内部使用),您首先需要消耗未完成/最后一个响应。DefaultHttpClientBasicClientConnectionManager

EntityUtils.consumeQuietly(httpResponse.getEntity());

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

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