我知道在其他地方会问相关的问题,但我的不同:)
我正在使用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()方法同步。
如果有人有任何意见,我会非常感激。
答案 0 :(得分:1)
SingleClientConnectionManager
在某种意义上是完全线程安全的,当多个执行线程使用它时,其内部状态是同步的并且始终是一致的。这并没有改变它只能分配单个连接的事实。因此,如果两个线程尝试租用连接,则只有一个可以成功,而另一个可能会获得'java.lang.IllegalStateException:无效使用SingleClientConnManager'
如果您的应用程序需要同时执行请求,那么您应该使用池连接管理器。