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.
沒有留言:
張貼留言