scheduleAtFixedRate
和scheduleWithFixedDelay
的文档说:
如果任务的任何执行遇到异常,则后续 执行被压制
假设我的任务是为了做一些网络工作而没有找到主机。这些任务不会再被执行吗?主机可能在下一刻重新上线。
假设文档正在讨论的是RuntimeException
的实例,就像数组索引超出范围一样,任务永远不会再被执行?如果我希望他们继续执行该怎么办?
答案 0 :(得分:3)
任务永远不会再被执行吗?
这就是“后续处决被压制”意味着,不是吗?
如果我希望他们继续执行该怎么办?
不要让RuntimeExceptions
和Errors
逃脱。
答案 1 :(得分:1)
检查由Scheduler执行的Runnable操作中的未捕获异常。默认情况下,JVM不会捕获它们并且线程崩溃时会被忽视。
我建议使用自定义ScheduledThreadPoolExecutor
,如下所示:
static class MyScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor {
public MyScheduledThreadPoolExecutor(int corePoolSize,ThreadFactory threadFactory) {
super(corePoolSize, threadFactory);
}
@Override
public ScheduledFuture<?> schedule(Runnable command, long delay,TimeUnit unit) {
return super.schedule(new SheduleExceptionCatcher(command), delay, unit);
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,long initialDelay, long period, TimeUnit unit) {
return super.scheduleAtFixedRate(new SheduleExceptionCatcher(command), initialDelay, period, unit);
}
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,long initialDelay, long delay, TimeUnit unit) {
return super.scheduleWithFixedDelay(new SheduleExceptionCatcher(command), initialDelay, delay, unit);
}
/** Wrap for Runnable - for error catching */
private static class SheduleExceptionCatcher implements Runnable {
private Runnable task;
public SheduleExceptionCatcher(Runnable task) {
this.task = task;
}
@Override
public void run() {
try {
task.run();
} catch (Throwable e) {
System.err.println("" + e); // or some logger probably
}
}
}
}
进行一些测试:
public static void main(String[] args) {
new MyScheduledThreadPoolExecutor(2, new PriorityThreadFactory("GeneralSTPool", Thread.NORM_PRIORITY)).scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
throw new RuntimeException("Test Error");
}
},3000, 3000, TimeUnit.MILLISECONDS);
while (true){}
}
将打印
java.lang.RuntimeException: Test Error
java.lang.RuntimeException: Test Error
java.lang.RuntimeException: Test Error
java.lang.RuntimeException: Test Error
java.lang.RuntimeException: Test Error
因此,即使抛出错误,您的任务也会永久执行。
答案 2 :(得分:1)
当我忘记在Runnable
内捕获异常时,不明白崩溃发生在哪里非常烦人。实际上我不需要忽略所有这些异常,我只需要确保不要忽视它们。为此,我创建了CatchyRunnable类,它是Runnable
的包装器,它记录异常并在需要时传播它们:
executorService.submit(new CatchyRunnable(new Runnable() {
@Override
public void run() {
throw new RuntimeException("log me");
}
});
您可以通过应用工厂方法模式使用更简洁的语法,我只是计划与lambdas一起使用:
executorService.submit(new CatchyRunnable(() -> {
throw new RuntimeException("log me");
});