【问题标题】:Unirest shutdown to exit programUnirest 关闭以退出程序
【发布时间】:2015-12-28 15:37:45
【问题描述】:

我尝试使用Unirest.get(...).asObjectAsync(...) 更新具有计划任务的资源。要停止使用 Unirest 的程序,您需要调用 Unirest.shutdown(); 以退出其事件循环和客户端。但是,如果某些线程在成功关闭后调用 Unirest 的请求方法,则程序无法退出。

以下代码是一个非常简单的示例:我启动一个线程,它在 1.5 秒后执行 GET 请求,并在成功时打印状态消息。同时在主线程上,Unirest 被关闭。 (请注意,此示例使用asStringAsync(...) 和一个非常简单的线程。)

import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.async.Callback;
import com.mashape.unirest.http.exceptions.UnirestException;

import java.io.IOException;

public class Main {
    public static void main(String... args) throws IOException, InterruptedException {
        new Thread(() -> {
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Unirest.get("http://example.org").asStringAsync(new Callback<String>() {
                @Override
                public void completed(HttpResponse<String> response) {
                    System.out.println(response.getStatusText());
                }

                @Override
                public void failed(UnirestException e) {
                    System.out.println("failed");
                }

                @Override
                public void cancelled() {
                    System.out.println("cancelled");
                }
            });
        }).start();
        Unirest.shutdown();
    }
}

我所期望的是以下任何一种情况:

  • 程序关闭,没有输出。
  • 程序关闭,我得到以下任何输出:状态消息,失败或取消。
  • 程序关闭但抛出异常,因为当 GET 请求发生时 Unirest 已经关闭。

我得到了什么:

  • 程序未关闭且 GET 请求成功,打印“OK”。

如何处理 Unirest 的优雅退出?我应该重组程序吗(如果是,如何重组)?

我在 Windows 上使用 Java 8,在 IntelliJ Idea 14.1.5 中运行代码。 我使用的唯一依赖项是:

<dependency>
    <groupId>com.mashape.unirest</groupId>
    <artifactId>unirest-java</artifactId>
    <version>1.4.7</version>
</dependency>

【问题讨论】:

    标签: java unirest


    【解决方案1】:

    在您的情况下,您已经生成了一个运行异步调用的线程。 shutdown() 调用在您的主线程中,因此在调用线程产生时,shutdown() 将被调用之前,可以首先调用 Unirest 的 asStringAsync() 方法。

    这是对..Async() 的第一次调用,它实例化了最终需要关闭的线程池 - 在您调用 shutdown 方法时没有要关闭的东西,所以这是不行的同上。它将在您创建的线程中实例化。

    这里的解决方案是删除您创建的线程,并使用 Unirest 提供给您的Future 对象。 Unirest 在您进行异步调用时会自行处理线程,您可以根据需要输入回调逻辑。

        public static void main(String... args) throws IOException, InterruptedException, ExecutionException {
        Future<HttpResponse<String>> asyncCall = Unirest.get("http://thecatapi.com/api/images/get?format=xml&results_per_page=20").asStringAsync(new Callback<String>() {
            @Override
            public void completed(HttpResponse<String> response) {
                System.out.println(response.getStatusText());
            }
    
            @Override
            public void failed(UnirestException e) {
                System.out.println("failed");
            }
    
            @Override
            public void cancelled() {
                System.out.println("cancelled");
            }
        });
        HttpResponse<String> httpResponse = asyncCall.get(); // Can also use Future.isDone(), etc
        // System.out.println(httpResponse.getBody());
        Unirest.shutdown();
    }
    

    【讨论】:

      【解决方案2】:

      asyncCall.get() 会阻塞调用,所以最好如下:

      asyncCall.thenAcceptAsync((result)->{   
      if (null != result && !result.isEmpty()) {
              // do your business logic after response and then close Unirest
              Unirest.shutdown();
               }
          });
         }
      

      但在清理资源的情况下,您始终可以重复使用创建的相同资源并注册一个关闭挂钩,该挂钩将在 JVM 关闭期间清除所有内容。

      参考:http://kong.github.io/unirest-java/#configuration

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多