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();