Difference between shutdown and shutdownNow of Executor Service
In summary, you can think of it that way:
shutdown()
will just tell the executor service that it can't accept new tasks, but the already submitted tasks continue to runshutdownNow()
will do the same AND will try to cancel the already submitted tasks by interrupting the relevant threads. Note that if your tasks ignore the interruption,shutdownNow
will behave exactly the same way asshutdown
.
You can try the example below and replace shutdown
by shutdownNow
to better understand the different paths of execution:
- with
shutdown
, the output isStill waiting after 100ms: calling System.exit(0)...
because the running task is not interrupted and continues to run. - with
shutdownNow
, the output isinterrupted
andExiting normally...
because the running task is interrupted, catches the interruption and then stops what it is doing (breaks the while loop). - with
shutdownNow
, if you comment out the lines within the while loop, you will getStill waiting after 100ms: calling System.exit(0)...
because the interruption is not handled by the running task any longer.
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.submit(new Runnable() {
@Override
public void run() {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("interrupted");
break;
}
}
}
});
executor.shutdown();
if (!executor.awaitTermination(100, TimeUnit.MICROSECONDS)) {
System.out.println("Still waiting after 100ms: calling System.exit(0)...");
System.exit(0);
}
System.out.println("Exiting normally...");
}
Comparison between shutting down an executor service (while awaiting termination) and wait cancellation of submitted tasks (using submit's futures)
In the proposed solution, wait should be called after shutdownNow() method invocation.
An unused ExecutorService should be shut down to allow reclamation of
its resources.
shutdownNow():-
- Transition the run state to Stop
- Interrupt the worker if started
- Drain the queue - Remove all the threads
Future.cancel (false):-
- Doesn't interrupt the running tasks
- The cancel attempt will fail if the task has already completed, has
already been cancelled, or could not be cancelled for some other
reason. You may need to have additional logic to handle different
scenarios. The shutdownNow() already handles those scenarios.
Short description and recommendation:-
Actually, having a
List
object itself is not thread-safeSingleton beans are stateless. It should not be maintaining the state
in the class level. Even if you declare this as prototype bean, it is
not a good practice to maintain the List (List is not thread safe) of
futures.
Internally, the executer service implementation classes such as ThreadPoolExecutor, ScheduledThreadPoolExecutor etc. takes care of all the thread safety issues. It uses BlockingQueue
to overcome the thread safety issues. Also, it handles exception and different states accordingly. You may need to understand all the internals (i.e. what is happening under the hood) to come up with a good custom solution.
The easy and best way is to use the standard implementations (ThreadPoolExecutor, ScheduledThreadPoolExecutor etc) available in the executor service implementations to avoid any adverse effect (i.e. memory leakage, thread safety issues).
Why executor.isShutdown() returns true when there are threads still running in it's pool?
The calls to shutdownNow()
or shutdown()
are not blocking. That is what is referred to in the docs.
So if you call shutdown()
or shutdownNow()
, you get control back immediately, not only after everything has gracefully shut down. If you want to wait for all executors/threads to terminate after the call to shutdown[Now]()
, you have to call awaitTermination(...)
, which will block until everything is cleaned up. This is probably what you want. Also see answers to a similar question here: Difference between shutdown and shutdownNow of Executor Service
Don't understand ExecutorService#shutdown
It means that the shutdown
method returns immediately. It does not wait for scheduled and already running tasks to complete before returning to its caller. This means that the ExecutorService can still take some time to clean up and terminate itself (which it will eventually do, after all running tasks have completed).
shutdown and awaitTermination which first call have any difference?
You should call shutdown
first. Otherwise, you might be waiting for a very long time, since awaitTermination
doesn't actually shut down your executor.
If you wanted to wait for tasks to complete, rather than wait for the executor to shut down, then you should use invokeAll
.
shutdownNow with executor service
You are right in your assumption, if the Future
times out, some hanging threads will remain. Even worse, shutdownNow()
will not even shutdown your pool thread (not to mention proprietary API threads). It merely stops accepting new jobs. ExecutorService
thread pool will terminate all threads once all running tasks finish.
What you can do is to try canceling the future and interrupting it. First handle InterruptedException
inside your future:
class ConnectThread implements Callbale<ApplicationConnection> {
public ApplicationConnection call() {
try {
return prioprietaryApi.connect();
} catch(InterruptedException e) {
prioprietaryApi.cleanUp();
throw e;
}
}
}
Now simply run:
future.cancel(true);
However your proprietary API might not handle InterruptedException
(it will not rethrow it from connect()
, moreover you might not have access to any cleanUp()
method.
In these circumstances just... forget about it. That Future
will eventually terminate and clean up after itself, ignoring the fact that you no longer wait for it. Of course this might lead to various scalability issues.
BTW if the only thing you want to achieve is limiting the maximum time given method runs, consider TimeLimiter
from guava.
Best way to shutdown ExecutorService in Java
But I am worried what if write something wrong the code in callable
task f.get() takes forever and the program will halt forever and never
exit.
That's a bug. You need to make sure that doesn't happen.
With codes above, I can make sure threads are closed after 10 seconds
No, you can't. Even shutdownNow()
doesn't actually guarantee that the executor threads are shut down (documentation):
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.
The ThreadPoolExecutor
tries to "shut down now" by interrupting all worker threads. You need to make sure that your tasks handle interrupts correctly.
Once your tasks stop correctly, you can estimate how long a shutdown should take based on your application and the tasks you're shutting down. Then you can do a graceful shutdown:
- Call
shutdown()
- Wait for an orderly shutdown for a reasonable amount of time using
awaitShutdown()
- If the executor is still running, call
shutdownNow()
and handle any outstanding tasks it returns.
Related Topics
Java - Removing Duplicates in an Arraylist
What's in an Eclipse .Classpath/.Project File
Difference Between Role and Grantedauthority in Spring Security
Running a Java Program from Another Java Program
Recursively List All Files Within a Directory Using Nio.File.Directorystream;
Populate Jtable with Large Number of Rows
Apache Httpclient Interim Error: Nohttpresponseexception
General Strategy to Resolve Java Memory Leak
How != and == Operators Work on Integers in Java
How to Express Dependency in Maven on Java Ee Features for Transition to Java 9
Regex: How to Escape Backslashes and Special Characters
How to Use Mockito When We Cannot Pass a Mock Object to an Instance of a Class
How to Correctly Use Custom Renderers to Paint Specific Cells in a Jtable
Is There a Way in Java to Determine If a Path Is Valid Without Attempting to Create a File