【问题标题】:OkHttpClient with Java Future java.io.InterruptedIOExceptionOkHttpClient 与 Java 未来 java.io.InterruptedIOException
【发布时间】:2021-11-29 01:50:33
【问题描述】:

我正在尝试制作一个网络抓取工具,它可以无限期地解析特定的 URL,中间会有一些延迟。 我有一个方法genericMonitor,它接受要解析的url和一个回调来返回结果。 使用SheduledExecutorService 重复调用此方法。代码如下:

ScheduledFuture<?> task = service.scheduleWithFixedDelay(() -> {
          try {
            genericMonitor(percent, url, idSupplier, callback);
          } catch (IOException connectException) {
            logger.error("Error in generic", connectException);
          }
        }, 0, delay, TimeUnit.MINUTES);
        tasks.put(link, task);

tasks 映射包含所有当前正在运行的任务。 我使用OkHttp Java 库发出 http 请求。 当我尝试使用task.cancel 取消任务时,我得到InterruptedIOException

java.io.InterruptedIOException: interrupted
    at okio.Timeout.throwIfReached(Timeout.java:146)
    at okio.Okio$1.write(Okio.java:76)
    at okio.AsyncTimeout$1.write(AsyncTimeout.java:180)
    at okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.java:179)
    at okio.RealBufferedSink.writeByte(RealBufferedSink.java:125)
    at okhttp3.internal.http2.Http2Writer.writeMedium(Http2Writer.java:265)
    at okhttp3.internal.http2.Http2Writer.frameHeader(Http2Writer.java:253)
    at okhttp3.internal.http2.Http2Writer.headers(Http2Writer.java:289)
    at okhttp3.internal.http2.Http2Connection.newStream(Http2Connection.java:253)
    at okhttp3.internal.http2.Http2Connection.newStream(Http2Connection.java:225)
    at okhttp3.internal.http2.Http2Codec.writeRequestHeaders(Http2Codec.java:117)
    at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:54)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:94)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:125)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:264)
    at okhttp3.RealCall.execute(RealCall.java:93)
    at org.dk.Bot.callRemoteWithProxy(Bot.java:82)
    at org.dk.Bot.genericMonitor(Bot.java:182)
    at org.dk.Bot.lambda$processCommand$1(Bot.java:129)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
    at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    at java.base/java.lang.Thread.run(Thread.java:832)

我不确定是什么问题

【问题讨论】:

    标签: java okhttp


    【解决方案1】:

    当您调用 cancel 并将参数 mayInterruptIfRunning 设置为 true 时会引发异常。

    ... 如果任务已经开始,则 ma​​yInterruptIfRunning 参数确定是否应中断执行该任务的线程以尝试停止该任务。 ...

    参数: mayInterruptIfRunning - 如果执行此任务的线程应该被中断,则为 true;否则,允许完成正在进行的任务

    因此它将中断任务并在您正在运行的任务中导致InterruptedIOException。如果您想允许正在进行的任务完成,请致电 cancel(false)

    【讨论】:

      【解决方案2】:

      感谢您的所有回答。我意识到调用cancel 并没有取消执行本身。它只设置标志。您需要在任务本身内部检查线程是否被中断并相应地处理。就我而言,我刚刚从该方法返回。

      【讨论】:

        【解决方案3】:

        来自 Oracle 文档InterruptedIOException 类:

        • I/O 操作已中断的信号。一个
        • 抛出InterruptedIOException 表示一个
        • 输入或输出传输已终止,因为线程
        • 执行被中断。字段 {@link #bytesTransferred}
        • 表示之前成功传输了多少字节
        • 发生中断。

        您正在尝试取消或中断执行 IO 操作的线程,我认为在“genericMonitor”方法中您有一些 IO 操作,或者当他在 catch 块中写入时您试图中断线程日志文件,所以这就是你得到这种类型的异常的原因。

        您可以在调用取消之前添加 isDone 以确保不会抛出异常。 或者您可以处理此异常并确保您的所有资源都已关闭(尝试使用资源),此链接可让您了解如何处理类似的异常类型:Handling InterruptedException in Java

        你也可以使用:boolean cancel(boolean mayInterruptIfRunning); 尝试阅读此方法的文档,看看它是否可以帮助您。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-03-11
          • 2020-12-17
          • 2020-07-08
          • 2018-11-23
          • 1970-01-01
          • 2016-06-05
          • 2014-03-04
          • 1970-01-01
          相关资源
          最近更新 更多