Java 实现超时任务的最佳方法

Java 实现超时任务的最佳方法,java,concurrency,timeout,executorservice,futuretask,Java,Concurrency,Timeout,Executorservice,Futuretask,我正在尝试实现一个TimeoutTask,它将在给定的超时后终止。以下是我所拥有的: import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.Objects; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Ex

我正在尝试实现一个
TimeoutTask
,它将在给定的超时后终止。以下是我所拥有的:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class TimeoutTask {

    private Long timeout;
    private TimeUnit unit;

    public TimeoutTask(Long timeout, TimeUnit unit) {
        this.timeout = timeout;
        this.unit = unit;
    }

    public <T> T execute(Callable<T> callable) {
        Objects.requireNonNull(timeout, "Timeout");
        Objects.requireNonNull(unit, "Time Unit");
        Objects.requireNonNull(callable, "Callable");

        ExecutorService service = 
                Executors.newFixedThreadPool(1);
        FutureTask<T> task = new FutureTask<T>(callable);
        service.execute(task);

        try {
            return task.get(timeout, unit);
        } catch (InterruptedException | ExecutionException | TimeoutException cause) {
            if(cause instanceof TimeoutException) {
                System.out.println("\nTimeout occured.");
                task.cancel(true);
            }
        } finally {
            System.out.println("Finally called.");
            service.shutdownNow();
        }

        return null;
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
        Callable<String> callable = () -> {         
            System.out.print("Enter something: ");
            BufferedReader consoleReader = 
                    new BufferedReader(new InputStreamReader(System.in));
            String str = consoleReader.readLine();
            return str;
        };

        TimeoutTask timeoutTask = new TimeoutTask(Long.valueOf(10), TimeUnit.SECONDS);
        timeoutTask.execute(callable);  
    }
}
在这种情况下,同样的事情发生了

注意:
可调用的
只是一个示例。

您调用

String str = consoleReader.readLine();
这意味着您使用的是经典的、分块的、不可中断的JavaIO。即使在超时之后,该方法仍保持阻塞,并且
shutdownNow()
也无法触及它,因为它也只是尝试中断线程

顺便说一句,我已经运行了您的代码,输出显示“Finally called”

更新
更新后的
可调用
与原来的一样不可中断。您必须调用声明抛出
InterruptedException
(例如
Thread.sleep()
)的方法,或者在循环中检查
Thread.interrupted()

您需要解决的问题是
System.in.read()
不响应中断。在

中查看如何绕过此问题谢谢您的回复,先生,我也有同样的想法,因此我更改了
可调用的
,如更新中所示。在这种情况下,同样的事情也发生了。是的
Thread.interrupted()
在循环中工作。因此,没有通用的方法来实现
超时任务
,此类调用方不需要考虑停止
线程
!没错,这是有意为之的:只有协作中断机制才能为您提供实施安全清理的机会。
String str = consoleReader.readLine();