ExecutorService Framework provides support for asynchronous computation.Basically it creates a thread pool for executing the tasks in separate threads for asynchronous execution.
Creating a Thread Pool of Fixed Size
ExecutorService executor = Executors.newFixedThreadPool(10);
The above code creates a thread pool with 10 threads.
execute and submit methods
The execute() method is void, and it doesn’t give any possibility to get the result of task’s execution or to check the task’s status (is it running or executed).
submit() submits a Callable or a Runnable task to an ExecutorService and returns a result of type Future.
Future<String> future = executorService.submit(callableTask);
InvokeAll and InvokeAny
ExecutorService support batch submitting of multiple callables at once via invokeAll(). This method accepts a collection of callables and returns a list of futures.
Another way of batch-submitting callables is the method invokeAny() which works slightly different to invokeAll(). Instead of returning future objects this method blocks until the first callable terminates and returns the result of that callable.
Shutting Down an ExecutorService
When you are done using the Java ExecutorService you should shut it down, so the threads do not keep running.
If your application is started via a main() method and your main thread exits your application, the application will keep running if you have an active ExexutorService in your application. The active threads inside this ExecutorService prevents the JVM from shutting down.
To terminate the threads inside the ExecutorService you call its shutdown() method. The ExecutorService will not shut down immediately, but it will no longer accept new tasks, and once all threads have finished current tasks, the ExecutorService shuts down. All tasks submitted to the ExecutorService before shutdown() is called, are executed.
If you want to shut down the ExecutorService immediately, you can call the shutdownNow() method. This will attempt to stop all executing tasks right away, and skips all submitted but non-processed tasks. There are no guarantees given about the executing tasks. Perhaps they stop, perhaps the execute until the end. It is a best effort attempt.
The ExecutorService awaitTermination() method will block the thread calling it until either the ExecutorService has shutdown completely, or until a given time out occurs.
One good way to shut down the ExecutorService (which is also recommended by Oracle) is to use both of these methods combined with the awaitTermination() method. With this approach, the ExecutorService will first stop taking new tasks, the wait up to a specified period of time for all tasks to be completed. If that time expires, the execution is stopped immediately.
In the below Example, the execution stops after 1 millisecond. So, all the tasks are not completed. Out of 100, around 50 odd tasks are completed in 1 millisecond.
The isTerminated() method returns true if all the tasks have been completed following shut down.
We need to execute isTerminated() only after executing either shutdown or shutdownNow. We can use isTerminated() in while loop to wait for the execution of all tasks before proceeding further with next set of codes.