在使用ScheduledExecutorService進(jìn)行周期性任務(wù)執(zhí)行時(shí),遇到一個(gè)問題:
- 如果Runnable#run()方法拋異常的話,該異常會(huì)被ScheduledExecutorService吞掉,同時(shí)ScheduledExecutorService的周期性任務(wù)會(huì)被停掉。(如果ScheduledExecutorService有多個(gè)周期性任務(wù)的話,只有這個(gè)scheduleAtFixedRate()會(huì)被停掉,其它的可以正常執(zhí)行)。
import java.util.Date;
import java.util.Locale;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Demo {
private final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(3);
private final Runnable runnable2 = () -> System.out.printf(Locale.CHINA, "[%s][%s]Runnable2 running...\n", new Date(), Thread.currentThread().getName());
public static void main(String[] args) {
Demo d = new Demo();
d.test();
}
public void test() {
executorService.scheduleAtFixedRate(this::executeRunnable1, 0, 1000, TimeUnit.MILLISECONDS);
executorService.scheduleAtFixedRate(runnable2, 0, 2000, TimeUnit.MILLISECONDS);
}
private void executeRunnable1() {
System.out.printf(Locale.CHINA, "[%s][%s]Runnable1 running...\n", new Date(), Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
throw new RuntimeException("My Exception");
} catch (Throwable t) { // Catch Throwable rather than Exception (a subclass).
System.err.println(String.format(Locale.CHINA, "[%s][%s]%s\n", new Date(), Thread.currentThread().getName(), e));
}
}
}
Solution1:
最簡單的Solution是在Runnable#run()方法中添加try-catch。
Solution2:
public void test() {
ScheduledFuture<?> scheduledFuture1 = executorService.scheduleAtFixedRate(this::executeRunnable1, 0, 1000, TimeUnit.MILLISECONDS);
try {
//可以捕捉到j(luò)ava.lang.RuntimeException: My Exception錯(cuò)誤,但是Runnable1不會(huì)持續(xù)執(zhí)行。
scheduledFuture1.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
executorService.scheduleAtFixedRate(runnable2, 0, 2000, TimeUnit.MILLISECONDS);
}