basichttpclient执行抛出“SingleClientConnManager:连接仍然分配”为什么?

时间:2012-03-12 11:21:46

标签: multithreading thread-safety httpclient

我知道在其他地方会问相关的问题,但我的不同:)

我正在使用BasicHttpClient和HttpPoster将内容发送给第三方服务。我在使用单个bean发布内容的JMS侦听器的场景中使用它。我不认为这是一个问题,因为BasicHttpclient使用SingleClientConnectionManager并且javadoc说

This connection manager maintains only one active connection at a time. Even though this class is thread-safe it ought to be used by one execution thread only.

线程安全是关键在这里)但是,当我有两个同时请求时,我得到了经典

java.lang.IllegalStateException: Invalid use of SingleClientConnManager: connection still allocated.

为什么我这样做?我没有清理任何东西,因为basicclient根据文档做了。

我的bean构造函数:

HttpParams params = new BasicHttpParams();
params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, SMS_SOCKET_TIMEOUT);
params.setParameter(CoreConnectionPNames.SO_TIMEOUT, SMS_SOCKET_TIMEOUT);
params.setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET,
            encoding);
params.setParameter(CoreProtocolPNames.HTTP_ELEMENT_CHARSET,
            encoding);
httpclient = new DefaultHttpClient(params);

poster = new HttpPost(mtUrl);
poster.setHeader("Content-type", contentType);

responseHandler = new BasicResponseHandler();

我的代码来运行一个帖子:

public String[] sendMessage(MtMessage mess) throws MtSendException, MtHandlingException {

    StringEntity input;

    try {
        String postBody = assembleMessagePostBody(mess);
        input = new StringEntity(postBody);
        poster.setEntity(input);
        ResponseHandler<String> responseHandler = new BasicResponseHandler();
        String response = httpclient.execute(poster, responseHandler);
        return new String[]{extractResponseMessageId(response)};
    } catch(HttpResponseException ee){
        throw new MtSendException(ee.getStatusCode(), ee.getMessage(), false);
    } catch (IOException e) {
        throw new MtSendException(0, e.getMessage(), false);
    } finally{

    }
}

我认为尽管可以同时从多个JMS侦听器线程调用“sendMessage”,但它是线程安全的,因为connectionhandler是线程安全的。我想我可能只是让sendMessage()方法同步。

如果有人有任何意见,我会非常感激。

1 个答案:

答案 0 :(得分:1)

SingleClientConnectionManager在某种意义上是完全线程安全的,当多个执行线程使用它时,其内部状态是同步的并且始终是一致的。这并没有改变它只能分配单个连接的事实。因此,如果两个线程尝试租用连接,则只有一个可以成功,而另一个可能会获得'java.lang.IllegalStateException:无效使用SingleClientConnManager'

如果您的应用程序需要同时执行请求,那么您应该使用池连接管理器。