【问题标题】:Java - HttpClient not releasing threadsJava - HttpClient 不释放线程
【发布时间】:2021-03-27 17:45:24
【问题描述】:

我正在使用 Java 11 的内置 HTTP 客户端,但遇到了一个奇怪的问题,即客户端不释放线程。我有以下代码:

public static void main(String[] args) throws InterruptedException, IOException, URISyntaxException {
    HttpClient client = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.ALWAYS).build();
    HttpResponse<Void> response;

    HttpRequest request = HttpRequest.newBuilder().uri(new URI("http://127.0.0.1:4321")).headers("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString("{}")).build();

    response = client.send(request, HttpResponse.BodyHandlers.discarding());
}

我正在使用 maven 的 exec 插件运行应用程序,但出现以下错误:

[WARNING] thread Thread[HttpClient-1-Worker-0,5,com.example.httpclient.App] was interrupted but is still alive after waiting at least 14995msecs
[WARNING] thread Thread[HttpClient-1-Worker-0,5,com.example.httpclient.App] will linger despite being asked to die via interruption
[WARNING] thread Thread[HttpClient-1-Worker-1,5,com.example.httpclient.App] will linger despite being asked to die via interruption
[WARNING] thread Thread[HttpClient-1-Worker-2,5,com.example.httpclient.App] will linger despite being asked to die via interruption
[WARNING] NOTE: 3 thread(s) did not finish despite being asked to  via interruption. This is not a problem with exec:java, it is a problem with the running code. Although not serious, it should be remedied.
[WARNING] Couldn't destroy threadgroup org.codehaus.mojo.exec.ExecJavaMojo$IsolatedThreadGroup[name=com.example.httpclient.App,maxpri=10]

客户端似乎没有正确释放其线程。有趣的是,如果我注释掉发送请求的代码(同时保留创建客户端的代码),那么上述警告就会消失。

如果我在末尾添加System.exit(0),那么警告也会消失,但我仍然想知道为什么内置客户端会发生这种情况?客户端、请求或响应上没有关闭方法,所以我认为我没有泄漏资源。

我什至将客户端设置为 null 并手动调用 GC,即使问题仍然存在。很困惑这是怎么回事。

【问题讨论】:

    标签: java java-11 maven-exec-plugin


    【解决方案1】:

    HttpClient 使用带有守护线程的内部线程池。似乎客户端在垃圾收集时没有明确关闭此线程池。

    您看到的警告与您的 Maven 插件部署的基础架构有关。似乎其他人也遇到过类似的问题(例如参见 couldn't destroy threadgroup org.codehaus.mojo.exec.ExecJavaMojo$IsolatedThreadGroup[name=SitemapCheck.SitemapAction,maxpri=10])。

    抑制警告的可能解决方法是向HttpClient.Builder 提供Executor,并在您的主方法中关闭此Executor

    https://docs.oracle.com/en/java/javase/15/docs/api/java.net.http/java/net/http/HttpClient.Builder.html#executor(java.util.concurrent.Executor)

    作为记录,如果没有向HttpClient.Builder 提供执行器,HttpClient 使用由Executors.newCachedThreadPool(ThreadFactory) 返回的执行器。

    【讨论】:

      猜你喜欢
      • 2016-02-28
      • 1970-01-01
      • 2014-06-14
      • 2016-03-05
      • 2011-09-13
      • 1970-01-01
      • 2018-11-13
      • 1970-01-01
      • 2012-11-28
      相关资源
      最近更新 更多