简体   繁体   中英

Future.cancel(false) returning true for task in execution

Future.cancel(false) should, in my opinion, only return true if it was actually possible to prevent the task's execution.

But from code below we can see that it is contradicting.

As the task is canceld it should not print "Not expecting this statement!!!"

public class Test {
    public static void main(String[] args) throws InterruptedException {
        ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
        final boolean[] canceled = { false };
        ScheduledFuture<?> future = executor.schedule(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    if (canceled[0])
                        System.out.println("Not expecting this statement!!!");
                } catch (InterruptedException e) {
                }
            }
        }, 0, TimeUnit.SECONDS);
        Thread.sleep(100);
        canceled[0] = future.cancel(false);

        executor.shutdown();
        executor.awaitTermination(2, TimeUnit.SECONDS);
    }
}

Unfortunately output of this program is "Not expecting this statement!!!"

Can some one explain this behavior.

Because you call canceled[0] = future.cancel(false); with parameter false . From javadoc of Future.cancel :

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.

@param mayInterruptIfRunning {@code true} if the thread executing this task should be interrupted; otherwise, in-progress tasks are allowed to complete

When you call cancel , your task has already started and you allow it to complete, so cancel operation is actually successful and return true , if you call canceled[0] = future.cancel(true); , you'll not see the output.

In your code, boolean[] canceled is shared between two threads and there is no synchronized access to this variable. So, the results will be unexpected. Also from the documentation of https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#cancel(boolean) , it will return false if the task could not be cancelled, typically because it has already completed normally. Try adding a log after cancelling the task to see which one gets executed first (though it might not help always)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM