在下面的代码中,我按照预期在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;
}
}
答案 0 :(得分:8)
您需要在超时时取消任务(并中断其线程)。这就是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;
}
答案 1 :(得分:4)
您的Callable必须能够在需要时快速停止。
您的代码:
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;
}
由于致电Thread.sleep()
,已经能够做到这一点。重点是futureTask.cancel(true)
将中断其他线程,您的代码需要对此中断作出反应。 Thread.sleep()
这样做。如果您没有使用Thread.sleep()
或其他可中断的阻止代码,则必须自己检查Thread.currentThread().isInterrupted()
,并在发现此问题时尽快退出(例如通过抛出new InterruptedException()
)是真的。
您需要从异常处理程序中调用futureTask.cancel(true);
来取消和中断运行任务的线程。
我的建议是了解中断机制(这是一篇很棒的文章:Dealing with InterruptedException),然后使用它。
答案 2 :(得分:1)
一旦你发现了TimeoutException,你需要调用你的任务的cancel(true)方法......
或通过调用shutdownNow()...
关闭ExecutorService或通过调用System.exit(0)
退出VM取决于您的需求