Reference
Git: ForkJoinPoolErrorMain.java
前篇: ForkJoinPool - Workstealing
Next: ForkJoinPool - Thread Management
前篇: ForkJoinPool - Workstealing
Next: ForkJoinPool - Thread Management
Error Handling
如果 fork 出去的 task/action 有 exception, 呼叫 join 的時候要注意 catch exception.
不然 task/action 就死掉失控了.
而且可怕的是: 不會有 log.
Codes
這段程式是說每個 action 有個 id, 奇數 id 會報 exception.
Exception without catch when join
先是不要 catch 的情況
main action 也沒有完成.(main action id = -1)
這個程式就可以印 error, 而且 maintask 可以執行完成
public class ForkJoinPoolErrorMain { static final CountDownLatch latch = new CountDownLatch(1); public static void main(String[] params) throws InterruptedException { ForkJoinPool pool = new ForkJoinPool(2); ScheduledExecutorService s = Executors.newScheduledThreadPool(1); s.scheduleAtFixedRate(() -> System.out.println(pool), 0, 1, TimeUnit.SECONDS); pool.submit(new ErrorAction(MAIN_TASK_ID)); latch.await(10, TimeUnit.SECONDS); pool.shutdown(); s.shutdown(); } static class ErrorAction extends RecursiveAction { public static final int MAIN_TASK_ID = -1; private final int id; ErrorAction(int id) { this.id = id; } private boolean isSubTask() { return id >= 0; } @Override protected void compute() { if (isSubTask()) { if (id % 2 == 1) { throw new IllegalStateException("Error when id is odd number"); } } else { List<ErrorAction> actions = IntStream.range(0,10).mapToObj(idx -> new ErrorAction(idx)).collect(Collectors.toList()); actions.forEach(ErrorAction::fork); actions.forEach(action -> { action.join(); }); latch.countDown(); } System.out.println("compute done. id=" + id); } } }輸出如下, 不過一個 exception 也沒有.
main action 也沒有完成.(main action id = -1)
Exception with catch statement
有 catch 的程式如下
public class ForkJoinPoolErrorMain { static final CountDownLatch latch = new CountDownLatch(1); public static void main(String[] params) throws InterruptedException { ForkJoinPool pool = new ForkJoinPool(2); ScheduledExecutorService s = Executors.newScheduledThreadPool(1); s.scheduleAtFixedRate(() -> System.out.println(pool), 0, 1, TimeUnit.SECONDS); pool.submit(new ErrorAction(MAIN_TASK_ID)); latch.await(10, TimeUnit.SECONDS); pool.shutdown(); s.shutdown(); } static class ErrorAction extends RecursiveAction { public static final int MAIN_TASK_ID = -1; private final int id; ErrorAction(int id) { this.id = id; } private boolean isSubTask() { return id >= 0; } @Override protected void compute() { if (isSubTask()) { if (id % 2 == 1) { throw new IllegalStateException("Error when id is odd number"); } } else { List<ErrorAction> actions = IntStream.range(0,10).mapToObj(idx -> new ErrorAction(idx)).collect(Collectors.toList()); actions.forEach(ErrorAction::fork); actions.forEach(action -> { try { action.join(); } catch (Exception ex) { System.err.println(ex + ", id=" + action.id); } }); latch.countDown(); } System.out.println("compute done. id=" + id); } } }
Exception with ExecutorService
如果是 ExecutorService, 就算是丟 RuntimeException.
ExecutorService 還是會把 exception 印到 console 上.
public class ExecutorServiceWithExceptionMain { public static void main(String[] params) { ExecutorService ex = Executors.newSingleThreadExecutor(); ex.execute(() -> { throw new IllegalStateException("test throw illegalState"); }); ex.shutdown(); } }即使是直接丟 exception 也會印到 console.
沒有留言:
張貼留言