b_pcakes
b_pcakes

Reputation: 2540

Shutting down ExecutorService

According to documentation, when shutdown() is invoked, any tasks that were already submitted (I assume via submit() or execute) will be executed. When shutdownNow() is invoked, the executor will halt all tasks waiting to be processed, as well as attempt to stop actively executing tasks.

What I would like to clarify is the exact meaning of "waiting to be processed." For example, say I have an executor, and I call execute() on some number of Runnable objects (assume all of these objects effectively ignore interruptions). I know that if I now call shutdown, all of these objects will finish executing, regardless.

However, if I call shutdownNow at this point, will it have the same effect as calling shutdown? Or are some of the objects not executed? In other words, if I want an executor to exit as fast as possible, is my best option always to call shutdownNow(), even when the Runnables passed to the executor all effectively ignore interruptions?

Upvotes: 2

Views: 8016

Answers (3)

Stephen C
Stephen C

Reputation: 719376

What I would like to clarify is the exact meaning of "waiting to be processed".

It means all tasks whose run() method has not yet been called (by the executor).

If I call shutdownNow at this point, will it have the same effect as calling shutdown?

No.

Or is it possible that some of the objects will not be executed?

That is correct.

In other words, if I want an executor to exit as fast as possible, is my best option always to call shutdownNow(), even when the Runnables passed to the executor all effectively ignore interruptions?

That is correct.

Better still, recode the Runnables to pay attention to interrupts ... or put a timeout on the shutdown ...

Upvotes: 1

zapl
zapl

Reputation: 63955

Let's say you have this fabulous Runnable that is not interruptible for 10 seconds once it's started:

Runnable r = new Runnable() {
    @Override
    public void run() {
        long endAt = System.currentTimeMillis() + 10000;
        while (System.currentTimeMillis() < endAt);
    }
};

And you have an executor with just 1 thread and you schedule the runnable 10 times:

ExecutorService executor = Executors.newFixedThreadPool(1);
for (int i = 0; i < 10; i++)
    executor.execute(r);

And now you decide to call shutdown:

  • The executor continues for the full 10 x 10 seconds and everything scheduled will be executed. The tasks don't see that you're shutting down their executor. shutdown can be used if you want a "short lived" executor just for a few tasks. You can immediately call shutdown and it will get cleaned up later.

Alternatively shutdownNow():

  • Takes 10 seconds. The already running task is attempted to be interrupted, but that obviously has no effect so it continues to run. The other 9 tasks that were still waiting in the queue are "cancelled" and returned to you as List so you could do something with them, like schedule them later. Could also take 0 seconds if the first task is not yet started. You'd get all tasks back. The method is used whenever you want to abort an entire executor.

Upvotes: 2

Caffeinated
Caffeinated

Reputation: 12484

The API for shutdownNow method says that :

There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate.

source

Upvotes: 0

Related Questions