【问题标题】:Executors vs threads执行者与线程
【发布时间】:2012-10-09 22:12:05
【问题描述】:

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

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 分钟之后?

【问题讨论】:

  • 今天我做了一个关于线程的讲座。我告诉我的学生们:如果我觉得淘气,我会有代码供你在考试中分析。该代码可能包含 t.run(),而不是 t.start()。
  • 看我的更新已经解决了

标签: java multithreading executorservice


【解决方案1】:

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

至于处理ScheduledExecutorService中的异常——如果你调用Future.get(),如果原来的任务抛出异常,它会抛出ExecutionException,暴露原来的异常是原因:

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

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

【讨论】:

  • 谢谢,但有没有办法将异常传播到主/调用线程?
  • @Bober02:使用Future.get() 就是这样,真的。毕竟,您不希望原始线程在任意时间点抛出异常,对吗?
  • 你将如何在 N 次尝试或 N 分钟后停止周期性计划?
【解决方案2】:

你可以这样捕捉它:

    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 throws 中运行的代码出现异常,它将在调用 @987654322@ 时重新抛出,并包装到 ExecutionException

编辑:

关于停止计划任务,已经是discussed and solved了。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 2012-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多