Java ExecutorService

The Java ExecutorService is the interface that allows us to execute tasks on threads asynchronously. It is present in the java.util.concurrent package. The ExecutorService helps maintain a pool of threads and assigns them tasks. It also provides the facility to queue up tasks until there is a free thread available if the number of tasks is more than the threads available.

Additionally, the ExecutorService interface provides ways to control how tasks are carried out. These methods that submit tasks for execution and return a Future reflecting the task's awaiting results, include submit(Runnable task) and submit(Callable<T> task). Additionally, the ExecutorService is gracefully terminated by the shutdown() method, which permits tasks that have already been submitted to finish before ending.

Another technique, shutdownNow(), stops the processing of pending tasks immediately and tries to stop all presently operating processes. Furthermore, until all tasks have finished executing following a shutdown request, the timeout occurs, or the current thread is interrupted; whichever comes first, the awaitTermination(long timeout, TimeUnit unit) method blocks. For Java programs, this interface offers a flexible and effective way to handle multiple tasks at once.

Java ExecutorService

Methods of Java ExecutorService

MethodDescription
boolean awaitTermination(long timeout, TimeUnit unit)This method blocks the task to enter ExecutorService until all the tasks have completed after the shutdown request, or the given timeout occurs, or the current thread is interrupted, whichever happens first.
<T> ListinvokeAll(Collection<? extends Callable<T>> tasks)This method executes the list of tasks given and returns the list of Futures which contain the results of all the tasks when completed.
<T> ListinvokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)This method executes the list of tasks given and returns the list of Futures which contain the results of all the tasks when completed or the timeout expires, whichever occurs first.
<T> T invokeAny(Collection<? extends Callable<T>> tasks)This method executes the list of tasks given and returns the result of one task which gets completed without throwing any exception.
<T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout,TimeUnit unit)This method executes the list of tasks given and returns the result of one task which gets completed without throwing any exception before the timeout elapses.
boolean isShutdown()This method returns whether the given executor is shut down or not.
boolean isTerminated()This method returns true if all tasks have executed after shutdown.
void shutdown()This method allows completion of previously submitted tasks to the ExecutorService and doesn?t allow any other tasks to be accepted.
ListshutdownNow()This method stops all the actively executing tasks, stops the execution of queued up tasks, and returns the list of tasks which are queued up.
<T> Future<T> submit(Callable<T> task)This method submits a value-returning task for execution and returns the Future, which represents the pending result of the task.
Future<?> submit(Runnable task)This method submits a task for execution and returns a Future representing that task. It returns null upon successful completion.
<T> Future<T> submit(Runnable task, T result)This method submits a task for execution and returns a Future representing that task.
void execute(Runnable command)Executes the given command at some time in the future.
<T> CompletionService<T> newCompletionService()Creates a new CompletionService that uses the given executor for running tasks and returns it.
ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)Schedules the given command to run after a specified delay, returning a ScheduledFuture representing that task.
ScheduledFuture<?> schedule(Callable<V> callable, long delay, TimeUnit unit)Schedules the given callable to run after a specified delay, returning a ScheduledFuture representing that task.
ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given period.
ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given delay between the termination of one execution and the commencement of the next.

ExecutorService Java Program

Filename: ExecutorServiceExample.java

Output:

Java ExecutorService

Explanation

In this program, we are creating an ExecutorService with ten threads and assigning it an anonymous runnable implementation which performs a task to print "ExecutorService" and after its task is over, we are shutting down the executor service.

How to use Java ExecutorService?

Instantiating ExecutorService

We can use Java ExecutorService to create a single thread, a pool of threads, or a scheduled pool of threads. The Executors class provides factory methods to instantiate an ExecutorService as follows-

Assigning Tasks to ExecutorServices

To assign a task to ExecutorService, we can use the following methods-

  • execute(Runnable task)
  • submit(Runnable task) / submit(Callable<T> task)
  • invokeAny(Collection<? extends Callable<T>> tasks)
  • invokeAll(Collection<? extends Callable<T>> tasks)

Example of Assigning a Task to ExecutorService Using execute() Method

The Java ExecutorService's execute() method takes in a runnable object and performs its task asynchronously. After making the call to execute method, we call the shutdown method, which blocks any other task to queue up in the executorService.

Filename: ExecutorServiceExample.java

Output:

ExecutorService

Explanation

This Java program demonstrates the usage of an ExecutorService with a single thread obtained via Executors.newSingleThreadExecutor(). After creating the executor service, a task represented by an anonymous inner class implementing the Runnable interface is submitted using the execute method. Inside the run() method of this task, "ExecutorService" is printed to the console.

Finally, the shutdown method is called on the executor service to gracefully shut it down after the submitted task completes execution. It ensures that no new tasks are accepted by the executor service, and it waits for the existing task to complete before terminating.

Example of Assigning a Task to ExecutorService Using submit() Method

The submit() method takes in a runnable object and returns a Future object. This object is later on used to check the status of Runnable whether it has completed execution or not.

Filename: ExecutorServiceExample.java

Output:

ExecutorService

Explanation

This Java program creates an ExecutorService with a single thread using Executors.newSingleThreadExecutor(). It then submits a task to the executor service to print "ExecutorService" to the console using the submit method. This demonstrates asynchronous task execution with a single-threaded executor service.

Example of Assigning a Task to ExecutorService Using invokeAny() Method

The invokeAny() method takes a collection of Callablle objects or objects of classes implementing Callable. This method returns the future object of the callable object which gets successfully executed first.

Filename: ExecutorServiceExample.java

Output:

result = Task 1

Explanation

The use of an ExecutorService with a single thread acquired via Executors is demonstrated in this Java programme.executeSingleThread() in a new way. It uses HashSet to generate a set of Callable tasks, each of which returns a text that represents a task. The list of callables now includes these tasks. The list of callables is then passed to the ExecutorService's invokeAny method, which delivers the outcome of a single job that has been finished. Once every job has finished running, the result is displayed on the console and the executor service is eventually gently terminated by means of the shutdown method.

Example of Assigning a Task to ExecutorService Using invokeAll() Method

The invokeAll() method takes in a Collection of Callable objects having tasks and returns a list of Future objects containing the result of all the tasks.

Filename: ExecutorServiceExample.java

Output:

future.get = Task 1
future.get = Task 3
future.get = Task 2

Explanation

This Java programme makes use of an ExecutorService that it received via Executors and has one thread.executeSingleThread() in a new way. It adds Callable tasks to the set after creating them. The set of callables is then passed to the ExecutorService's invokeAll method, which returns a list of Future objects that reflect the tasks' outcomes. After that, iterating through the list of futures, the output of each task is printed. Finally, when every job has finished running, the executor service is gently terminated by using the shutdown function.

How to shut down ExecutorService?

Once we are done with our tasks given to ExecutorService, then we have to shut it down because ExecutorService performs the task on different threads. If we do not shut down the ExecutorService, the threads will keep running, and the JVM would not shut down.

The process of shutting down can be done by the following three methods-

1. shutdown() Method

This method initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks are accepted. It allows the ExecutorService to gracefully shut down after completing all submitted tasks.

2. shutdownNow() Method

This method attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution. It forcibly terminates the ExecutorService, potentially interrupting ongoing tasks.

3. awaitTermination() Method

Blocks the calling thread until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first. This method allows the calling thread to wait for the termination of the ExecutorService before proceeding with further actions.


Next TopicJava Tutorial