如何立即关闭 InputStream?

How to close InputStream immediately?

有一个无限的输入流,我通过以下简单的代码行读取了传入的消息:

InputStream inputStream = response.getBody();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
    while ((event = reader.readLine()) != null) {
        // do the work
    } 
}
System.out.println("Connection closed");

一切都很好。但是我希望能够在一定时间内没有新消息时断开连接。

第一个问题是 readLine 方法会阻塞执行,直到收到下一条消息。这就是我想避免的。我发现 CloasableReader - Bufferedreader 的包装器允许从外部中断 readLine。所以我只是将 BufferedReader 替换为 CloasableReadervoalá - 我退出了 while 循环。但是带有 "Connection closed" 消息的行仍然没有被执行。

我稍微修改了一下代码...

InputStream inputStream = response.getBody();
BufferedReader reader = null;
try {
    reader = new BufferedReader(new InputStreamReader(inputStream));
    while ((event = reader.readLine()) != null) {
        // do the work
    } 
} finally {
    if (reader != null) {
        reader.close();
    }
}
System.out.println("Connection closed");

...并意识到实际上 close 方法也会卡住,等待下一条消息接收。因为 Guava 的 TimeLimiter::callWithTimeout 方法对我不起作用。实际上它工作正常(包装上面示例中标记为 "do the work" 的代码)但我不能离开 try-catch-finaly 块。

内部 BufferedReader::close 调用 InputStreamReader::close,后者又调用 InputStream::close,这就是问题所在。我只是在等待,并将永远这样做。

我不知道现在该怎么办。如何强制关闭流?

您的问题看起来与 非常相似。您可以尝试在那里找到有关 callWithTimeout.

的线索

如果您的输入流来自某个套接字,您可以尝试不带 callWithTimeout 的版本并添加 Socket.setSoTimeout,因此在指定次数后从 InputStream 读取时会抛出 java.net.SocketTimeoutException毫秒。

编辑: 由于您使用的是 ClientHttpResponse,您可以像这样设置读取和连接超时

    @Component
    public static class RestTemplateInitializer implements ApplicationListener<ApplicationReadyEvent> {

        public static HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();

        @Override
        public void onApplicationEvent(ApplicationReadyEvent e) {
            clientHttpRequestFactory.setConnectTimeout(10000);
            clientHttpRequestFactory.setReadTimeout(10000);
        }


    }