Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cancelling a future task in java [duplicate]

I want to cancel a task submitted to ExecutorService thus allowing the corresponding thread to pick a new task from the queue.

Now this question have been answered many times on this forum.... like checking Thread.currentThread().interrupt() or catch (InterruptedException e). But if the flow of control spans across multiple methods then putting these checks makes the code clumsy. So if possible please suggest some elegant ways in java to achieve this functionality.

The problem that I'm facing is that future.cancel won't actually cancel the task. Instead it just sends an InterruptedException to the executing task and it's the task's responsibility to mark itself complete and release the thread.

So what I did is that I had to put the below block of code whenever an exception gets thrown anywhere in the execution which obviously doesn't look good !

if(e instanceof InterruptedException) {
                    throw e;
                }

So, how to achieve this functionality in following code snippet:

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 {

    }
like image 981
gautam Avatar asked Jul 03 '17 11:07

gautam


People also ask

How to cancel Future task Java?

Learn to cancel a task submitted to an executor service if the task still has to be executed and/or has not been completed yet. We can use the cancel() method of Future object that allows making the cancellation requests.

What is cancellation in Java?

The cancel method takes a single boolean argument. If the argument is true , cancel sends the background task an interrupt. Whether the argument is true or false , invoking cancel changes the cancellation status of the object to true . This is the value returned by isCancelled .

How do Futures work in Java?

A Future represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation.

Why use Java Future?

The Future class in Java is another way to write asynchronous code. By using Future and FutureTask, you can write a method that does long computation but returns immediately. Those methods, instead of returning a result, return a Future object. You can later get the result by calling the Future.


1 Answers

It does not matter if you interrupt the Callable or not, because at that point it's already too late

try{
  MyClass2 myClass2 = new MyClass2();
  myClass2.method2();
} catch (Exception e){

Your call to future1.cancel(true); after Thread.sleep(2000) does not actually cancel the ongoing task (in this case your method2 call) it only means that it should have been cancelled before it started.

The docs point that out https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#cancel(boolean)

Attempts to cancel execution of this task. This attempt will fail if the task has already completed, has already been cancelled, or could not be cancelled for some other reason. If successful, and this task has not started when cancel is called, this task should never run. If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.

If you want to cancel a ongoing task you want to use a volatile boolean flag or something similiar.

like image 142
Murat Karagöz Avatar answered Sep 24 '22 02:09

Murat Karagöz