在TimeoutException之后如何让FutureTask返回?

在下面的代码中,我按照预期在100秒后捕获TimeoutException。 在这一点上,我希望代码退出main和程序终止,但它继续打印到控制台。 如何让任务在超时后停止执行?

private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool(); private static  T timedCall(Callable c, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException { FutureTask task = new FutureTask(c); THREAD_POOL.execute(task); return task.get(timeout, timeUnit); } public static void main(String[] args) { try { int returnCode = timedCall(new Callable() { 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; } } 

您需要在超时时取消任务(并中断其线程)。 这就是cancel(true)方法的用途。 :

 private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool(); private static  T timedCall(FutureTask 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 task = new FutureTask(new Callable() { 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; } 

您的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.sleep()或其他可中断的阻塞代码,你必须自己检查Thread.currentThread().isInterrupted() ,并尽快退出(例如通过抛出new InterruptedException() )你发现这是真的。

你需要调用futureTask.cancel(true); 从您的exception处理程序取消并中断运行您的任务的线程。

我的建议是了解中断机制(这是一篇很棒的文章: 处理InterruptedException ),并使用它。

一旦捕获到TimeoutException,就需要调用任务的cancel(true)方法……

或通过调用shutdownNow()关闭您的ExecutorService …

或通过调用System.exit(0)退出VM

根据您的需要