ExecutorServiceに送信されたタスクをキャンセルして、対応するスレッドがキューから新しいタスクを選択できるようにします。javaで将来のタスクをキャンセルする
この質問はこのフォーラムで何度も答えられています.... Thread.currentThread().interrupt()
またはcatch (InterruptedException e)
のようにチェックしてください。しかし、コントロールの流れが複数の方法にまたがっている場合は、これらのチェックを行うことでコードが不器用になります。可能であれば、この機能を実現するために、Javaでいくつかの優雅な方法を提案してください。
私が直面している問題はfuture.cancelが実際にタスクをキャンセルしないことです。代わりに実行中のタスクにInterruptedException
を送信するだけで、スレッド自身を完了してスレッドを解放するのはタスクの責任です。
だから何私がやったことは、私は例外が明らかに良い見ていない実行中の任意の場所に投げられますたびのコードの下にブロックを入れていたということです!
if(e instanceof InterruptedException) {
throw e;
}
だから、どのように次のコードスニペットでこの機能を達成するために:その時点で、それはすでに手遅れだからあなたは、Callable
かを中断した場合
public class MonitoringInParallelExp {
public static void main(String[] args) throws InterruptedException {
MyClass1 myClass1 = new MyClass1();
ExecutorService service = Executors.newFixedThreadPool(1);
Future<String> future1 = service.submit(myClass1);
Thread.sleep(2000);
System.out.println("calling cancel in Main");
future1.cancel(true);
System.out.println("finally called cancel in Main");
service.shutdown();
}
}
class MyClass1 implements Callable<String> {
@Override
public String call() throws Exception {
try{
MyClass2 myClass2 = new MyClass2();
myClass2.method2();
} catch (Exception e){
if(e instanceof InterruptedException) {
System.out.println("call:"+"e instanceof InterruptedException="+"true");
throw e;
}
System.out.println("Got exception in method1. " + e);
}
System.out.println("returning Myclass1.method1.exit");
return "Myclass1.method1.exit";
}
}
class MyClass2 {
public void method2() throws Exception{
try{
MyClass3 myClass3 = new MyClass3();
myClass3.method3();
} catch (Exception e){
if(e instanceof InterruptedException) {
System.out.println("method2:"+"e instanceof InterruptedException="+"true");
throw e;
}
System.out.println("Got exception in method2. " + e);
// in case the exception isn't InterruptedExceptionm, do some work here
}
}
}
class MyClass3 {
public void method3() throws Exception{
try{
Thread.sleep(10000);
} catch (Exception e){
if(e instanceof InterruptedException) {
System.out.println("method3:"+"e instanceof InterruptedException="+"true");
throw e;
}
System.out.println("Got exception in method3. " + e);
throw new MyException();
}
}
}
class MyException extends Exception {
}
future1.cancel(true)は、主スレッドが2000 msだけスリープしているのに対して、method3は10000 ms完了するため、InterruptedExceptionを送信します。 method3は、例外がinstanceof InterruptedExceptionかどうかをチェックします。そうであれば、それは呼び出し元に渡されます(method2)。 私は、ワークフロー全体でこのチェックをどこにでも残して、最終的にMyClass1.call()メソッドに渡すことを心配していません。 この機能を実現する他のエレガントな方法はありますか? – gautam
@gautam - コールバックメカニズムを使用します。オブジェクトを他のクラスに渡し、InterruptedExceptionの間にメソッドをキャッチします。コールバックメカニズムについては、https://stackoverflow.com/questions/36449040/executing-java-callback-on-a-new-thread/36451028#36451028を参照してください。 –