java 如何让 FutureTask 在 TimeoutException 之后返回?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1281237/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I get FutureTask to return after TimeoutException?
提问by deltanovember
In the code below, I'm catching a TimeoutException after 100 seconds as intended. At this point I would expect the code to exit from main and the program to terminate but it keeps printing to the console. How do I get the task to stop executing after timeout?
在下面的代码中,我按预期在 100 秒后捕获 TimeoutException。在这一点上,我希望代码从 main 退出,程序终止,但它继续打印到控制台。如何让任务在超时后停止执行?
private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool();
private static <T> T timedCall(Callable<T> c, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
FutureTask<T> task = new FutureTask<T>(c);
THREAD_POOL.execute(task);
return task.get(timeout, timeUnit);
}
public static void main(String[] args) {
try {
int returnCode = timedCall(new Callable<Integer>() {
public Integer call() throws Exception {
for (int i=0; i < 1000000; i++) {
System.out.println(new java.util.Date());
Thread.sleep(1000);
}
return 0;
}
}, 100, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
return;
}
}
回答by Alexey Romanov
You need to cancel your task on timeout (and interrupt its thread). That's what cancel(true)method is for. :
您需要在超时时取消您的任务(并中断其线程)。这就是cancel(true)方法的用途。:
private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool();
private static <T> T timedCall(FutureTask<T> task, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
THREAD_POOL.execute(task);
return task.get(timeout, timeUnit);
}
public static void main(String[] args) {
try {
FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>() {
public Integer call() throws Exception {
for (int i=0; i < 1000000; i++) {
if (Thread.interrupted()) return 1;
System.out.println(new java.util.Date());
Thread.sleep(1000);
}
return 0;
}
});
int returnCode = timedCall(task, 100, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
task.cancel(true);
}
return;
}
回答by Peter ?tibrany
Your Callable must to be able to stop quickly, when needed.
您的 Callable 必须能够在需要时快速停止。
Your code:
您的代码:
public Integer call() throws Exception {
for (int i=0; i < 1000000 && !task.cancelled(); i++) {
System.out.println(new java.util.Date());
Thread.sleep(1000); // throws InterruptedException when thread is interrupted
}
return 0;
}
Is already able to do that thanks to calling Thread.sleep(). Point is that futureTask.cancel(true)will interrupt other thread, and your code needs to react to this interruption. Thread.sleep()does that. If you didn't use Thread.sleep()or other interruptible blocking code, you would have to check Thread.currentThread().isInterrupted()by yourself, and quit as soon as possible (e.g. by throwing new InterruptedException()) when you find this to be true.
由于调用了,已经能够做到这一点Thread.sleep()。重点是futureTask.cancel(true)会中断其他线程,您的代码需要对这种中断做出反应。Thread.sleep()这样做。如果您没有使用Thread.sleep()或其他可中断的阻塞代码,则必须Thread.currentThread().isInterrupted()自己检查,并new InterruptedException()在发现这是真的时尽快退出(例如通过 throw )。
You need to call futureTask.cancel(true);from your exception handler to cancel and interrupt thread which runs your task.
您需要futureTask.cancel(true);从异常处理程序中调用以取消和中断运行您的任务的线程。
My advice is to learn about interruption mechanism (this is great article: Dealing with InterruptedException), and use it.
我的建议是了解中断机制(这篇很棒的文章:处理 InterruptedException)并使用它。
回答by Zed
Once you caught the TimeoutException, you need to call the cancel(true) method of your task ...
一旦捕获到 TimeoutException,就需要调用任务的 cancel(true) 方法...
or shut down your ExecutorService by calling shutdownNow() ...
或通过调用 shutdownNow() 关闭您的 ExecutorService ...
or quit the VM by calling System.exit(0)
或通过调用 System.exit(0) 退出 VM
depending on your needs
根据您的需要

