Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/magento/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Apache Httpclient中止导致错误的请求_Java_Apache Httpclient 4.x - Fatal编程技术网

Java Apache Httpclient中止导致错误的请求

Java Apache Httpclient中止导致错误的请求,java,apache-httpclient-4.x,Java,Apache Httpclient 4.x,我有一个程序需要解决几个问题。对于每个问题,它可以并行地尝试几种不同的算法。一旦一个算法解决了这个问题,我希望其他算法能立即终止。有些算法是通过HTTP请求访问的:您向服务器发布问题,阻塞,服务器返回答案。如果另一个线程在服务器返回之前找到了答案,我希望该线程取消http请求 我最初使用的是Spring的RestTemplate,但找不到这个功能。最终我偶然发现了Apache的httpclient(我使用的是org.Apache.httpcomponents:httpclient:4.4.1)。

我有一个程序需要解决几个问题。对于每个问题,它可以并行地尝试几种不同的算法。一旦一个算法解决了这个问题,我希望其他算法能立即终止。有些算法是通过HTTP请求访问的:您向服务器发布问题,阻塞,服务器返回答案。如果另一个线程在服务器返回之前找到了答案,我希望该线程取消http请求

我最初使用的是Spring的RestTemplate,但找不到这个功能。最终我偶然发现了Apache的httpclient(我使用的是org.Apache.httpcomponents:httpclient:4.4.1)。Apache Httpclient说它可以,所以我使用它如下:

    // fields
        private final Lock lock;
        private final AtomicBoolean activeSolve;
        private HttpPost post;
        private final CloseableHttpClient httpClient = HttpClients.createDefault();


public String makePost() {
    post = new HttpPost("some url");
    final StringEntity stringEntity = new StringEntity("some json string", ContentType.APPLICATION_JSON);
    post.setEntity(stringEntity);
    try {
        lock.lock();
        activeSolve.set(true);
        lock.unlock();
        try (final CloseableHttpResponse httpResponse = httpClient.execute(post)) {
            final String response = EntityUtils.toString(httpResponse.getEntity());
            return response;
        }
    } catch (IOException e) {
        if (post.isAborted()) {
            log.trace("Web request was aborted");
            return "aborted";
        } else {
            throw new RuntimeException("Could not contact server", e);
        }
    } finally {
        lock.lock();
        activeSolve.set(false);
        lock.unlock();
    }
}
我有从另一个线程中断的代码

   public void interrupt() {
        lock.lock();
        if (activeSolve.get()) {
            post.abort();
        }
        lock.unlock();
    }
这可能会起作用,但经过1000个问题(我发现很难重现,但如果我运行足够长的时间,我最终会看到),我将得到以下堆栈跟踪:

java.lang.IllegalStateException: Connection is not open
at org.apache.http.util.Asserts.check(Asserts.java:34)
at org.apache.http.impl.BHttpConnectionBase.ensureOpen(BHttpConnectionBase.java:132)
at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseEntity(DefaultBHttpClientConnection.java:177)
at org.apache.http.impl.conn.CPoolProxy.receiveResponseEntity(CPoolProxy.java:172)
at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:274)
at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:124)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:271)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
at ... my classes
如果我注释掉中断代码并禁用中断,我就不会看到这个错误。但据我所知,我正确地使用了图书馆


如果有人熟悉这个库,您能告诉我我是如何错误地使用它的,或者什么事件序列可能会触发该错误吗?否则,如果有另一个库取消您认为可靠的http请求,我就不必绑定到这个apache库

我不确定这是否是问题的根源,但HttpPost被标记为非线程安全(请参阅)。这很可能会给您带来问题,并可能解释您在这里看到的内容

由于它不是线程安全的,因此很难确切地知道它将如何失败,这甚至可能取决于JVM实现。

  • 如果您稍微改变一下方法,并通过线程池生成线程,并且一旦收到响应,就可以关闭线程池
  • 如果我在上面的方法中没有错的话,我会看到HttpClient的实例是共享的。试着把它移到关键部分(方法)中,然后看到导致上述问题的中断消失了
  • 原子变量在中断方法中的使用非常好

这一点你绝对是对的。但是这些文档还说(在我上面列出的链接中):“HttpClient执行的HTTP请求可以通过调用HttpUriRequest#abort()方法在执行的任何阶段中止。这个方法是线程安全的,可以从任何线程调用”您可能对我的