Search code examples
javaconcurrencyexecutorservicescheduledexecutorservice

Why ScheduledExecutorService cannot be shutted down from the Runnable command itself?


I want to schedule a command which will be executed in every 1 second. The command will increment a counter and when the counter would reach certain limit, the execution will be stopped and the ExecutorService will shut down. So I have written following code snippet:

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class SchedulerTest {

    private ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
    private ScheduledFuture<?> scheduledTask;

    private AtomicInteger counter = new AtomicInteger(0);

    public SchedulerTest() {

    }

    private void check() {
        Runnable task = new Runnable() {

            @Override
            public void run() {
                int currentValue = counter.incrementAndGet();                   
                System.out.println(currentValue);

                if(currentValue == 5) {
                    scheduledTask.cancel(false);

                    scheduler.shutdown();
                    while(!scheduler.isTerminated()) {}
                }
            }
        };

        scheduledTask = scheduler.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS);                                
    }

    public static void main(String[] args) {
        new SchedulerTest().check();
    }
}

The above code is solely for demonstrating purpose.

Now I can see following in my Eclipse console:

console image

The red button on the top right, shows that the JVM is still running as the ExecutorService is running. I have placed log inside the while and I have seen the loop is never terminated.

I would like to know what is the reason behind this behaviour? Is there any way to terminate the ExecutorService from the Runnable command itself?

I am using JDK6.


Solution

  • Inside the run method you check for termination status of the threadpool:

    while(!scheduler.isTerminated()) {}
    

    This will do the following:

    • The thread executing that runnable will enter the loop.
    • Since the thread is still "active" i.e. has not finished run the condition will be true ( "not terminated = true" ).
    • That will keep the thread in the loop forever.

    So delete that "while" and the threadpool will be terminated as expected.

    P.S.: If you want to wait on the main execution line for the pool to be terminated you can use awaitTermination.