【问题标题】:Interrupt a long running Jersey Client operation中断一个长时间运行的 Jersey 客户端操作
【发布时间】:2014-07-02 20:14:36
【问题描述】:

我正在使用 Oracle Jersey Client,并试图取消长时间运行的 getput 操作。

Client 构造为:

JacksonJsonProvider provider = new JacksonJsonProvider(new ObjectMapper());
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getSingletons().add(provider);
Client client = Client.create(clientConfig);

以下代码在工作线程上执行:

File bigZipFile = new File("/home/me/everything.zip");

WebResource resource = client.resource("https://putfileshere.com");
Builder builder = resource.getRequestBuilder();

builder.type("application/zip").put(bigZipFile); //This will take a while!

我想取消这个长期运行的put。当我尝试中断工作线程时,put 操作继续运行。据我所知,泽西客户端没有尝试检查Thread.interrupted()

在使用 AsyncWebResource 而不是 WebResource 以及在 Builder.put(..) 调用中使用 Future.cancel(true) 时,我看到了相同的行为。

到目前为止,我想出的唯一解决方案是在 ContainerListener 中抛出 RuntimeException

client.addFilter(new ConnectionListenerFilter(
  new OnStartConnectionListener(){
    public ContainerListener onStart(ClientRequest cr) {
      return new ContainerListener(){
        public void onSent(long delta, long bytes) {

          //If the thread has been interrupted, stop the operation
          if (Thread.interrupted()) {
            throw new RuntimeException("Upload or Download canceled");
          }

          //Report progress otherwise

        }
      }...    

我想知道是否有更好的解决方案(可能在创建 Client 时)可以正确处理可中断 I/O 而无需使用 RuntimeException

【问题讨论】:

  • 是上传数据需要这么长时间还是在服务器上处理?
  • @isnot2bad 是上传数据。假设一个 20MB 的文件在连接速度较慢的情况下可能需要相当长的时间才能上传。
  • 同样的问题,在 2015 年,我一直想知道为什么人们创建的库没有明确的取消机制。我想我会使用 Apache Http 客户端。

标签: java multithreading jersey httpconnection cancellation


【解决方案1】:

我想知道是否有更好的解决方案(可能在创建客户端时)可以在不使用 RuntimeException 的情况下正确处理可中断 I/O。

是的,只有在代码正在监视中断或调用其他监视中断的方法(例如Thread.sleep(...))时,才能中断线程。

从侦听器中抛出异常听起来不是一个坏主意。我当然会创建您自己的 RuntimeException 类,例如 TimeoutRuntimeException 或其他东西,以便您可以专门捕获和处理它。

要做的另一件事是关闭正在写入的底层 IO 流,这会导致 IOException 但我不熟悉 Jersey,所以我不确定您是否可以访问连接。

啊,这是一个想法。与其放置File,不如在从File 读取但也有超时的BufferedInputStream 上放置某种扩展。因此,Jersey 将从缓冲区中读取数据,如果超时到期,它会在某些时候抛出 IOException

【讨论】:

  • 感谢您的回复!在某个时候,我最终写了一个InterruptableInputStream;扩展InputStream 的类。它在覆盖每个InputStream 方法时检查currentThread 中断,如果线程被中断则抛出IOException。两种解决方案似乎都同样有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-17
  • 2012-02-13
  • 1970-01-01
相关资源
最近更新 更多