【问题标题】:Why ScheduledExecutorService doesn't print stack trace?为什么 ScheduledExecutorService 不打印堆栈跟踪?
【发布时间】:2012-10-15 13:11:55
【问题描述】:

为什么我们在这个例子中看不到堆栈跟踪?

public class NoStackTraceTester implements Runnable  {
    private static final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

    private ScheduledFuture<?> lifeCheckFuture;

    @Override
    public void run() {
        lifeCheckFuture = startLifecheck();
    }

    private ScheduledFuture<?> startLifecheck()
    {
        Runnable lifeCheck = new Runnable()
        {
            @Override
            public void run()
            {
                System.out.println("sending lifecheck ...");
                throw new RuntimeException("bang!");
            }
        };
        return scheduler.scheduleAtFixedRate(lifeCheck, 1000, 1000, TimeUnit.MILLISECONDS);
    }

    public static void main(String[] args) {
        new NoStackTraceTester().run();
    }
}

如果您尝试注释异常,您将执行 lifecheck 函数的重复任务。 但是如果抛出异常,线程会停止但没有细节:(

你知道为什么吗?

【问题讨论】:

  • 是否只发生在预定的执行器服务上?您是否尝试过将任务提交给单线程执行器?

标签: java exception-handling scheduled-tasks


【解决方案1】:

ExecutorService 将任何捕获的 Throwable 放置在 Future 对象中。如果你检查这个,你可以看到抛出了什么异常。这并不总是可取的,因此您可能必须在 run() 方法中捕获并处理或记录任何异常。

注意:一旦异常逃逸,任务将不再重复。

Runnable lifeCheck = new Runnable() {
    @Override
    public void run() {
        try {
            System.out.println("sending lifecheck ...");
            throw new RuntimeException("bang!");
        } catch(Throwable t) {
            // handle or log Throwable
        }
    }
};

【讨论】:

    【解决方案2】:

    如果您需要异常报告,您必须自己插入处理代码。 ExecutorService 不会自动将异常跟踪发送到标准输出,它不会自动发送非常好,因为这在生产代码中很少需要。

    基本上是这样的:

    public void run()
    {
       try {
         System.out.println("sending lifecheck ...");
         throw new RuntimeException("bang!");
       } catch (Throwable t) { t.printStackTrace(); }
    }
    

    【讨论】:

      【解决方案3】:

      ThreadPoolExecutor 中的 afterExecute() 方法可以被覆盖:

      class MyThreadPoolExecutor extends ThreadPoolExecutor {
          public MyThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
                  TimeUnit unit, BlockingQueue<Runnable> workQueue) {
              super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
          }
      
          @Override
          public void afterExecute(Runnable r, Throwable t) {
              super.afterExecute(r, t);
              // If submit() method is called instead of execute()
              if (t == null && r instanceof Future<?>) {
                  try {
                      Object result = ((Future<?>) r).get();
                  } catch (CancellationException e) {
                      t = e;
                  } catch (ExecutionException e) {
                      t = e.getCause();
                  } catch (InterruptedException e) {
                      Thread.currentThread().interrupt();
                  }
              }
              if (t != null) {
                  // Exception occurred
                  System.err.println("Uncaught exception is detected! " + t
                          + " st: " + Arrays.toString(t.getStackTrace()));
              }
              // ... Perform cleanup actions
          }
      }
      
      final class MyTask implements Runnable {
          @Override public void run() {
              System.out.println("My task is started running...");
              // ...
              throw new ArithmeticException(); // uncatched exception
              // ...
          }
      }
      
      public class ThreadPoolExecutorHandler {
          public static void main(String[] args) {
              // Create a fixed thread pool executor
              ExecutorService threadPool = new MyThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS,
                      new LinkedBlockingQueue<>());
              threadPool.execute(new MyTask());
              // ...
          }
      }
      

      来源:https://medium.com/@aozturk/how-to-handle-uncaught-exceptions-in-java-abf819347906(请注意,我将此处发布的代码修改为不重新执行,因为问题只要求打印堆栈跟踪)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-03
        • 1970-01-01
        • 1970-01-01
        • 2015-07-27
        • 2020-07-25
        • 2018-07-06
        相关资源
        最近更新 更多