runnable中的异常似乎会杀死线程池

问题描述 投票:0回答:1

我有一个要定期运行的运行库。在特定的运行中,我相信可运行对象遇到了空指针,但控制台上未显示任何异常。运行失败后,它将再也不会运行。我有两个问题:

  1. 如果存在空指针,为什么控制台上没有显示该指针
  2. 即使特定运行失败,以后如何再次执行计划任务?
scheduler = Executors.newScheduledThreadPool(1);
MyRunnable mr = new MyRunnable(this.data);
scheduler.scheduleWithFixedDelay(mr, 0, STATUS_SENDER_PERIOD, TimeUnit.MILLISECONDS);
java exception threadpool runnable
1个回答
0
投票

回答您的问题,

1]之所以看不到任何异常,是因为FutureTask#setException中调用的FutureTask#run有效地吞噬了它。为了能够记录异常,您应该创建一个新类扩展ScheduledThreadPoolExecutor并覆盖afterExecute方法,如下所示:

@Override
protected void afterExecute(Runnable r, Throwable t) {
    if (t == null && r instanceof Future<?>) {
        try {
            Object result = ((Future<?>) r).get();
         } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
         } catch (ExecutionException e) {
            t = e;
         }
    }

    if (t != null) {
        t.printStackTrace();
    }
}

或者像这样直接在返回的get上调用ScheduledFuture

var executor = Executors.newSingleThreadScheduledExecutor();
var future = executor.scheduleAtFixedRate(new MyRunnable(null), 1, 1, TimeUnit.SECONDS);

try {
    future.get();

} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}

2)重新运行失败的可运行对象的最简单方法是:

while (true) {
    try {
        future.get();
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
     }
}

但是恕我直言,这种方法不是最干净的。正确编码您的Runnable#run方法以处理异常将是一个更好的解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.