Executor Lifecycle in Java

Executor lifecycle management determines when an executor accepts new tasks and how it transitions toward termination. The main controls are `shutdown()` for orderly shutdown and `shutdownNow()` for attempted immediate shutdown.

An `ExecutorService` normally starts accepting tasks as soon as it is created and used. Calling `shutdown()` stops acceptance of new tasks but allows already submitted tasks to finish, including tasks waiting in the executor's queue.

Calling `shutdownNow()` also rejects new submissions, but it additionally attempts to interrupt tasks that are currently running and returns tasks that were queued but never started. An interruption is only a request: a task can ignore interruption or fail to respond promptly.

After shutdown begins, further task submissions are rejected, typically with `RejectedExecutionException`. The executor reaches the terminated state only after shutdown has begun and all relevant worker activity has completed.

`awaitTermination()` can be used after shutdown to wait for termination for a specified duration. The lifecycle can be observed with methods such as `isShutdown()` and `isTerminated()`. A common graceful pattern is `shutdown()`, followed by `awaitTermination()` when the caller needs to wait for completion.

Key points

Interview questions

What happens if you submit a task after calling `shutdown()`?

The executor no longer accepts new tasks once shutdown has been initiated. A submission such as `execute()` or `submit()` is rejected, normally by throwing `RejectedExecutionException`. Tasks that were already submitted before shutdown can continue according to the executor's shutdown policy.

What is the difference between `shutdown()` and `shutdownNow()`?

`shutdown()` stops the executor from accepting new tasks but allows previously submitted tasks to complete. `shutdownNow()` also stops accepting new tasks and attempts to interrupt tasks that are currently running. It returns tasks that were queued but never started. Because interruption is cooperative, `shutdownNow()` does not guarantee immediate termination of running tasks.

What is the difference between `isShutdown()` and `isTerminated()`?

`isShutdown()` becomes true after shutdown has been initiated. The executor may still have running or queued work at that point. `isTerminated()` becomes true only after the executor has completed termination. Therefore, an executor can be shut down without yet being terminated.

Does `shutdownNow()` forcibly kill a running Java thread?

No. `shutdownNow()` attempts to interrupt threads executing tasks; it does not forcibly kill those threads. A task must cooperate with interruption, commonly by responding to interruption-aware blocking methods or checking its interrupted status. Code that ignores interruption may continue running after `shutdownNow()` returns.