我正在尝试实现一个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);
}
}
它正在工作,如果没有给出输入,我可以看到超时消息。但是,该过程不会终止。以下是 Eclipse 控制台的屏幕截图,请参见突出显示的部分:
当我提供任何输入时,该过程立即终止。我FutureTask#cancel
从 catch 块也从 finally 块调用我要求通过调用来关闭服务,ExecutorService#shoutDownNow
我可以看到它正在打印 finally 被调用。
- 如果超时,如何停止正在执行的进程?
- 有没有更好的方法来实现这一目标?
我正在使用Java 8。
参考:
更新
在Marko Topolnik的回答中说原因是 Java IO 不中断;所以我将其更改Callable
为:
Callable<Long> callable = () -> {
long i = 0;
for(; i <Long.MAX_VALUE;i++){
}
return i;
};
对于这种情况,同样的事情发生了。
注意:这Callable
只是一个示例。