私のコードスニペット:
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
Task t = new Task(response,inputToPass,pTypes,unit.getInstance(),methodName,unit.getUnitKey());
Future<SCCallOutResponse> fut = executor.submit(t);
response = fut.get(unit.getTimeOut(),TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
// if the task is still running, a TimeOutException will occur while fut.get()
cat.error("Unit " + unit.getUnitKey() + " Timed Out");
response.setVote(SCCallOutConsts.TIMEOUT);
} catch (InterruptedException e) {
cat.error(e);
} catch (ExecutionException e) {
cat.error(e);
} finally {
executor.shutdown();
}
コードでInterruptedException
とExecutionException
を処理するにはどうすればよいですか?
そして、どのような場合に、これらの例外はスローされますか?
ExecutionException
とInterruptedException
は2つの非常に異なるものです。
ExecutionException
は、実行中のスレッドがスローした例外をすべてラップするため、たとえば、スレッドが何らかの種類のIOを実行していて、IOException
がスローされた場合) 、それはExecutionException
にラップされて再スローされます。
InterruptedException
は、問題が発生したことを示すものではありません。これは、現在の作業を完了して正常に終了できるように、停止するタイミングをスレッドに通知する方法を提供するためにあります。アプリケーションの実行を停止したいが、何かの途中でスレッドが実行していることをスレッドにドロップさせたくないとします(これをデーモンスレッドにした場合に起こります)。したがって、アプリケーションがシャットダウンされているとき、私のコードはこれらのスレッドで割り込みメソッドを呼び出し、それらに割り込みフラグを設定します。次にこれらのスレッドが待機またはスリープしているときに、割り込みフラグをチェックしてInterruptedException
をスローします、スレッドが従事している無限ループ処理/スリープロジックから抜け出すために使用できます(スレッドが待機もスリープもしない場合は、定期的に割り込みフラグを確認できます)。これがインスタンスです。論理フローを変更するために使用されている例外の例。まったくログに記録する唯一の理由は、何が起こっているのかを表示するサンプルプログラム、または割り込みロジックが正しく機能していない問題をデバッグしている場合です。
InterruptedException
は、計算が完了する前に待機中のスレッドでinterrupt
が呼び出された場合にスローされます。
ExecutionException
は、関連する計算(この場合はTask
)自体が例外をスローした場合にスローされます。
これをどのように処理するかは、完全にアプリケーションに依存します。
編集:ここに中断されたデモがあります:
import Java.util.concurrent.*;
public class Test
{
public static void main(String[] args) throws Exception
{
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<String> future = executor.submit(new SlowCallable());
executor.submit(new Interruptor(Thread.currentThread()));
try
{
System.out.println(future.get());
}
catch (InterruptedException e)
{
System.out.println("I was interrupted");
}
}
private static class Interruptor implements Callable<String>
{
private final Thread threadToInterrupt;
Interruptor(Thread threadToInterrupt)
{
this.threadToInterrupt = threadToInterrupt;
}
public String call() throws Exception
{
Thread.sleep(2000);
threadToInterrupt.interrupt();
return "interrupted other thread";
}
}
private static class SlowCallable implements Callable<String>
{
public String call() throws Exception
{
Thread.sleep(5000);
return "finished";
}
}
}
IBM Developer Worksの記事 Dealing with InterruptedException には、InterruptedException
の処理方法に関するいくつかのアドバイスがあります。
3種類の例外を返すサンプルコード。
_import Java.util.concurrent.*;
import Java.util.*;
public class ExceptionDemo{
public static void main(String args[]){
int poolSize=1;
int maxPoolSize=1;
int queueSize=30;
long aliveTive=60;
ArrayBlockingQueue<Runnable> queue= new ArrayBlockingQueue<Runnable>(queueSize);
ThreadPoolExecutor executor= new ThreadPoolExecutor(poolSize,maxPoolSize,aliveTive,
TimeUnit.MILLISECONDS,queue);
List<Future> futures = new ArrayList<Future>();
for ( int i=0; i < 5; i++){
futures.add(executor.submit(new RunnableEx()));
}
for ( Iterator it = futures.iterator(); it.hasNext();){
try {
Future f = (Future)it.next();
f.get(4000,TimeUnit.MILLISECONDS);
}catch(TimeoutException terr){
System.out.println("Timeout exception");
terr.printStackTrace();
}
catch(InterruptedException ierr){
System.out.println("Interrupted exception:");
ierr.printStackTrace();
}catch(ExecutionException err){
System.out.println("Exeuction exception:");
err.printStackTrace();
Thread.currentThread().interrupt();
}
}
executor.shutdown();
}
}
class RunnableEx implements Runnable{
public void run() {
// code in here
System.out.println("Thread name:"+Thread.currentThread().getName());
try{
Random r = new Random();
if (r.nextInt(2) == 1){
Thread.sleep(2000);
}else{
Thread.sleep(4000);
}
System.out.println("eee:"+1/0);
}catch(InterruptedException irr){
irr.printStackTrace();
}
}
}
_
出力:
_Thread name:pool-1-thread-1
Timeout exception
Thread name:pool-1-thread-1
Java.util.concurrent.TimeoutException
at Java.util.concurrent.FutureTask.get(FutureTask.Java:201)
at ExceptionDemo.main(ExceptionDemo.Java:20)
Thread name:pool-1-thread-1
Exeuction exception:
Java.util.concurrent.ExecutionException: Java.lang.ArithmeticException: / by zero
at Java.util.concurrent.FutureTask.report(FutureTask.Java:122)
at Java.util.concurrent.FutureTask.get(FutureTask.Java:202)
at ExceptionDemo.main(ExceptionDemo.Java:20)
Caused by: Java.lang.ArithmeticException: / by zero
at RunnableEx.run(ExceptionDemo.Java:49)
at Java.util.concurrent.Executors$RunnableAdapter.call(Executors.Java:471)
at Java.util.concurrent.FutureTask.run(FutureTask.Java:262)
at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1145)
at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:615)
at Java.lang.Thread.run(Thread.Java:744)
Interrupted exception:
Java.lang.InterruptedException
at Java.util.concurrent.FutureTask.awaitDone(FutureTask.Java:400)
at Java.util.concurrent.FutureTask.get(FutureTask.Java:199)
at ExceptionDemo.main(ExceptionDemo.Java:20)
Timeout exception
Java.util.concurrent.TimeoutException
at Java.util.concurrent.FutureTask.get(FutureTask.Java:201)
Thread name:pool-1-thread-1
at ExceptionDemo.main(ExceptionDemo.Java:20)
Thread name:pool-1-thread-1
Timeout exception
Java.util.concurrent.TimeoutException
at Java.util.concurrent.FutureTask.get(FutureTask.Java:201)
at ExceptionDemo.main(ExceptionDemo.Java:20)
_
TimeoutException :ブロッキング操作がタイムアウトしたときにスローされる例外。
上記の例では、いくつかのタスクが(4秒のスリープのため)より多くの時間を要し、Future
に対するget()
の操作をブロックしています。
タイムアウトを増やすか、実行可能なタスクを最適化してください。
ExecutionException :例外のスローによって中止されたタスクの結果を取得しようとしたときにスローされる例外=>計算が例外をスローしました
上記の例では、このException
は_ArithmeticException: / by zero
_によってシミュレートされます
一般に、例で引用されているようにそれが取るに足らないものである場合は、根本原因を修正してキャッチする必要があります。
InterruptedException :スレッドが待機中、スリープ中、または占有されている場合にスローされ、アクティビティの前または最中にスレッドが中断されます。
上記の例では、このException
は、ExecutionException
中に現在のスレッドを中断することによってシミュレートされます。
一般に、動作しないことをキャッチする必要があります。