runnable 中的异常似乎会杀死线程池
Exception in a runnable appears to kill threadpool
我有一个 运行我想定期 运行 启用。在特定的 运行 上,我相信 运行nable 遇到了空指针,但控制台上没有显示异常。在失败 运行 之后,它再也不会 运行s。我有两个问题:
- 如果有空指针,为什么控制台上没有显示
- 即使特定的 运行 失败了,我怎样才能在将来再次执行计划任务 运行?
scheduler = Executors.newScheduledThreadPool(1);
MyRunnable mr = new MyRunnable(this.data);
scheduler.scheduleWithFixedDelay(mr, 0, STATUS_SENDER_PERIOD, TimeUnit.MILLISECONDS);
回答您的问题,
1) 您看不到任何异常的原因是 FutureTask#run
中调用的 FutureTask#setException
有效地吞噬了它。为了能够记录异常,您应该创建一个新的 class 扩展 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();
}
}
或者直接在返回的 ScheduledFuture
上调用 get
,如下所示:
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
方法来处理异常将是更好的解决方案。
我有一个 运行我想定期 运行 启用。在特定的 运行 上,我相信 运行nable 遇到了空指针,但控制台上没有显示异常。在失败 运行 之后,它再也不会 运行s。我有两个问题:
- 如果有空指针,为什么控制台上没有显示
- 即使特定的 运行 失败了,我怎样才能在将来再次执行计划任务 运行?
scheduler = Executors.newScheduledThreadPool(1);
MyRunnable mr = new MyRunnable(this.data);
scheduler.scheduleWithFixedDelay(mr, 0, STATUS_SENDER_PERIOD, TimeUnit.MILLISECONDS);
回答您的问题,
1) 您看不到任何异常的原因是 FutureTask#run
中调用的 FutureTask#setException
有效地吞噬了它。为了能够记录异常,您应该创建一个新的 class 扩展 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();
}
}
或者直接在返回的 ScheduledFuture
上调用 get
,如下所示:
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
方法来处理异常将是更好的解决方案。