仕事でCallableスレッドの処理がExceptionを拾えないのでRunnableに替えるという作業があったので本当にExceptionが取れないのか試してみました。
Callableの実装
package example;
import java.util.concurrent.Callable;
public class Call1 implements Callable<String> {
// callの中に実際の処理を書く。
public String call(){
String nonNum = "null";
System.out.println("init Call1");
// Exceptionを発生させる
System.out.println("print call " + Integer.parseInt(nonNum));
return "Call";
}
}
Runnableの実装
package example;
public class Run1 implements Runnable {
// callの中に実際の処理を書く。
public void run(){
String nonNum = "run";
System.out.println("init Run1");
// Exceptionを発生させる
System.out.println("print run " + Integer.parseInt(nonNum));
}
}
CallableとRunnableの呼び出し
package example;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Hello {
public static void main(String[] args) {
System.out.println("Hello World");
// ExecutorServiceを生成
ExecutorService ex = Executors.newSingleThreadExecutor();
try {
// Executorにスレッド Call1() の実行を依頼
Future<String> futureResult = ex.submit(new Call1());
} catch (Exception e) {
System.out.println("Catched Call1 Exception:" + e.getMessage());
}
try {
// Run1を実行
Run1 run = new Run1();
Thread thread = new Thread(run);
thread.start();
} catch (Exception e) {
System.out.println("Catched Run Exception:" + e.getMessage());
}
}
}
コンパイル
$ javac example/Hello.java example/Run1.java example/Call1.java
実行
$ java example.Hello
Hello World
init Call1
init Run1
Exception in thread "Thread-0" java.lang.NumberFormatException: For input string: "run"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.base/java.lang.Integer.parseInt(Integer.java:652)
at java.base/java.lang.Integer.parseInt(Integer.java:770)
at example.Run1.run(Run1.java:13)
at java.base/java.lang.Thread.run(Thread.java:834)
RunnableのExceptionが表示されるが、CallableのExceptionはキャッチできないし、mainのtry catchでもキャッチできない。
しかし、Callableはget()した時にExceptionがキャッチできるとご指摘があり再度試してみました。
ご指摘くださった方々ありがとうございました。
mainは次の様に修正。
package example;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ExecutionException;
public class Hello {
public static void main(String[] args) {
System.out.println("Hello World");
// ExecutorServiceを生成
ExecutorService ex = Executors.newSingleThreadExecutor();
try {
// Executorにスレッド Call1() の実行を依頼
Future<String> futureResult = ex.submit(new Call1());
String ret;
ret = futureResult.get();
System.out.println("ret=" + ret);
} catch (InterruptedException|ExecutionException e) {
System.out.println("Catched Call1 Exception:" + e.getMessage());
}
// Run1を実行
Run1 run = new Run1();
Thread thread = new Thread(run);
thread.start();
}
}
コンパイルして実行すると。両方のExceptionを取得することができました。
$ java example.Hello
Hello World
init Call1
Catched Call1 Exception:java.lang.NumberFormatException: For input string: "null"
init Run1
Exception in thread "Thread-0" java.lang.NumberFormatException: For input string: "run"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.base/java.lang.Integer.parseInt(Integer.java:652)
at java.base/java.lang.Integer.parseInt(Integer.java:770)
at example.Run1.run(Run1.java:13)
at java.base/java.lang.Thread.run(Thread.java:834)
うーむ。なぜCallableをRunnableに替える必要があったのか。