Java 中的简单超时

2022-09-01 01:37:21

任何人都可以指导我如何在java中使用简单的超时吗?基本上在我的项目中,我正在执行一个语句,它正在从调制解调器读取响应。但有时调制解调器没有响应。为此,我想添加一个超时。我正在寻找一个像这样的代码:br.readLine()

try {
    String s= br.readLine();
} catch(TimeoutException e) {
    System.out.println("Time out has occurred");
}

答案 1

您可以在这里找到您正在寻找的内容。它可能存在一种更优雅的方式来实现这一目标,但一种可能的方法就是

选项 1(首选):

final Duration timeout = Duration.ofSeconds(30);
ExecutorService executor = Executors.newSingleThreadExecutor();

final Future<String> handler = executor.submit(new Callable() {
    @Override
    public String call() throws Exception {
        return requestDataFromModem();
    }
});

try {
    handler.get(timeout.toMillis(), TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
    handler.cancel(true);
}

executor.shutdownNow();

选项 2:

final Duration timeout = Duration.ofSeconds(30);
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);

final Future<String> handler = executor.submit(new Callable() {
    @Override
    public String call() throws Exception {
        return requestDataFromModem();
    }
});

executor.schedule(new Runnable() {
    @Override
    public void run(){
        handler.cancel(true);
    }      
}, timeout.toMillis(), TimeUnit.MILLISECONDS);

executor.shutdownNow();

这些只是一个草案,以便您可以获得主要想法。


答案 2

如今,您可以使用

try {
    String s = CompletableFuture.supplyAsync(() -> br.readLine())
                                .get(1, TimeUnit.SECONDS);
} catch (TimeoutException e) {
    System.out.println("Time out has occurred");
} catch (InterruptedException | ExecutionException e) {
    // Handle
}

编辑:poseidon正确地指出,在超时的情况下,上述方法不会中断正在处理Future任务的基础线程。在没有中断的情况下,底层线程将继续处理未来的任务直至完成,而无法知道结果是否不再需要。通过中断,底层线程至少可以看到(如果它检查)它已被中断,从而允许它优雅地完成处理并退出。

对于 JDK 中执行阻塞 IO 的方法,按照约定,它们的实现是检查调用线程的中断状态(如果为 true,则抛出 InterruptedException)。因此,中断线程可以使其快速退出,即使可能无限等待的情况,例如从输入源读取。

无需进一步阐述,如果我们想在超时时中断底层 Thread,我们可以调整:

Future<String> future = CompletableFuture.supplyAsync(() -> br.readLine());
try {
    String s = future.get(1, TimeUnit.SECONDS);
} catch (TimeoutException e) {
    System.out.println("Time out has occurred");
    
    future.cancel(true);
} catch (InterruptedException | ExecutionException e) {
    // Handle
}

推荐