4

我正在尝试运行以下代码:

public static void main(String[] args){
    ScheduledExecutorService service = new ScheduledThreadPoolExecutor(2);

    Runnable r = new Runnable() {
        @Override
        public void run() {
            throw new RuntimeException();
        }
    };
    service.execute(r );
    ScheduledFuture<?> schedule = service.schedule(r, 0, TimeUnit.SECONDS);
    new Thread(r).run();
}

关于上述,我有以下问题:

  1. 有没有办法捕捉和响应执行者线程上发生的异常?
  2. 为什么创建的线程的异常显式传播到主线程,但使用执行器服务的两次执行都没有传播该错误?怎么会发现这个错误?

编辑:想到另一个问题:

  1. 如何停止我安排的给定定期任务,比如在 N 次重复或 N 分钟之后?
4

2 回答 2

7

问题 2 真的很简单——你实际上并没有开始一个新线程,你只是在调用run(),它在原始线程中同步运行。您应该调用start(),此时异常不会被传播回来。

至于处理 a 中的异常,ScheduledExecutorService如果调用,如果原始任务抛出异常,Future.get()它将抛出,将原始异常暴露为原因:ExecutionException

尝试检索因抛出异常而中止的任务的结果时抛出异常。可以使用该Throwable.getCause()方法检查此异常。

如果您需要响应异常而不阻塞将来完成,您可以将您的“真实”包装Runnable在另一个刚刚委托给原始run()方法的“真实”中,但使用适当的 try/catch 块。

于 2012-10-09T22:14:38.637 回答
6

你可以像这样抓住它:

    ScheduledFuture<?> schedule = service.schedule(r, 0, TimeUnit.SECONDS);
    try {
        Object get = schedule.get();
    } catch (InterruptedException ex) {
        ex.printStackTrace();
    } catch (ExecutionException ex) {
        ex.printStackTrace();
    }

如果运行的代码(Scheduled)ExecutorService 抛出异常,它将在调用时重新Future.get()抛出ExecutionException

编辑:

关于停止计划任务,已经讨论并解决了。

于 2012-10-09T22:15:20.523 回答