What is ExecutorService in Java and how to create it?

Last updated on Jun 14,2021 13.9K Views

What is ExecutorService in Java and how to create it?

edureka.co

Java programming language works very efficiently with multithreaded applications which require the tasks to be executed concurrently in a thread. It becomes difficult for any application to execute a large number of threads simultaneously. So to overcome this problem, Java comes with ExecutorService which is a sub-interface of the Executors framework. In this article, we will discuss the functionality of ExecutorService in Java. Following are the topics covered in this blog:

What is Executor Framework?

It is fairly easier to make and execute one or two threads simultaneously. But it becomes difficult when the number of threads increases to a significant number. Large multi-threaded applications will have hundreds of threads running simultaneously. Therefore it makes complete sense to separate the thread creation from thread management in an application.

The executor is a framework helps you in creating and managing threads in an application. The executor framework helps you in the following tasks.

ExecutorService in Java Example

It is a sub-interface of the executor framework that adds certain functionalities to manage the thread life cycle of an application. It also provides a submit() method which can accept both runnable and callable objects.

In the following example, we will create an ExecutorService with a single thread and then submit the task to be executed inside the thread.

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Example {
public static void main(String[] args) {
System.out.println(" Inside : " + Thread.currentThread().getName());
System.out.println("creating ExecutorService");
ExecutorService executorservice = Executors.newSingleThreadExecutor();
System.out.println("creating a runnable");
Runnable runnable = () -> {
System.out.println("inside: "+ Thread.currentThread().getName());
};
System.out.println("submit the task specified by the runnable to the executorservice");
executorservice.submit(runnable);
}
}
Output: Inside: main
        creating ExecutorService
        creating a runnable
        submit the task specified by the runnable to the executorservice
        inside: pool-1-thread-1

The above program shows how we can create an ExecutorService and execute a task inside the executor. If a task is submitted for execution and thread is currently busy executing another task, then the task will wait in a queue until the thread is free to execute it.

When you run the above program, the program will never exit. You will need to shut it down explicitly since the executor service keeps listening for new tasks.

Java ExecutorService Implementations

ExecutorService is very much similar to a thread pool. In fact, the implementation of the ExecutorService in the java.util.concurrent package is a threadpool implementation. The ExecutorService has the following implementations in the java.util.concurrent package:

ThreadPoolExecutor

The ThreadPoolExecutor executes the given tasks using one of its internally pooled threads.

Creating a threadPoolExecutor

int corePoolSize = 5;
int maxPoolSize = 10;
long keepAliveTime = 5000;
ExecutorService threadPoolExecutor = 
new threadPoolExecutor( corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());

ScheduledThreadPoolExecutor

The java.util.concurrent.ScheduledThreadPoolExecutor is an ExecutorService that can schedule tasks to run after a delay or to execute repeatedly with a fixed interval of time in between each execution.

Example

ScheduledExecutorService  scheduledexecutorservice = Executors.newScheduledThreadPool (5);
ScheduledFuture scheduledfuture = scheduledExecutorService.schedule(new Callable(){
public Object call() throws Exception{
System.out.println("executed");
return "called";
}
},
5,
TimeUnit.SECONDS);

ExecutorService Usage

There are a few different ways to delegate tasks to an ExecutorService.

Execute Runnable

Java ExecutorService execute(Runnable) takes a java.lang.Runnable object and executes it asynchronously.

ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(new Runnable(){
public void run(){
System.out.println("asynchronous task");
}
});
executorService.shutdown();

There is no way to get the result of the execute Runnable, for that you have to use the Callable.

Submit Runnable

Java ExecutorService submit(Runnable) method takes a Runnable implementation and returns a future object. The future object can be used to check if the Runnable has finished executing.

Future future = executorService.submit(new Runnable(){
public void run(){
System.out.println(:asynchronous task");
}
});
future.get(); //returns null if the task is finished correctly.

Submit Callable

The Java ExecutorService submit(Callable) method is similar to submit(Runnable) but it takes Java Callable instead of Runnable.

Future future = executorService.submit(new Callable(){
public Object call() throws Exception{
System.out.println("Asynchronous callable");
return "Callable Result";
}
});
System.out.println("future.get() = " future.get());
Output: Asynchroous callable
        future.get = Callable Result

invokeAny()

The invokeAny() method takes a collection of Callable objects. Invoking this method does not return any future, but returns the result of one of the Callable objects.

ExecutorService executorService = Executors.newSingleThreadExecutor();
Set<Callable<String>> callables = new HashSet<Callable<String>>();
callables.add(new Callable<String>(){
public String call() throws Exception{
return"task A";
}
});
callables.add(new Callable<String>(){
public String call() throws Exception{
return"task B";
}
});
callables.add(new Callable<String>(){
public String call() throws Exception{
return"task C";
}
});
String result = executorService.invokeAny(callables);
System.out.println("result = " + result);
executorService.shutdown();

When you run the above code, the result changes. It might be Task A, Task B and so on.

InvokeAll()

The invokeAll() method invokes all Callable objects passed as parameters. It returns the future objects which can be used to get the results of the execution of each Callable.

ExecutorService executorService = Executors.newSingleThreadExecutor();
Set<Callable<String>> callables = new HashSet<Callable<String>>();
callables.add(new Callable<String>(){
public String call() throws Exception{
return "Task A";
}
});
callables.add(new Callable<String>(){
public String call() throws Exception{
return "Task B";
}
});
callables.add(new Callable<String>(){
public String call() throws Exception{
return "Task C";
}
});
List<Future<String>> futures = executorService.invokeAll(callables);
for(Future<String> future: futures){
System.out.println(" future.get = " + future.get());
}
executorService.shutdown();

Runnable vs Callable

The runnable and callable interfaces are very similar to each other. The difference is visible in the declaration of the interfaces. Both the interfaces represent a task that can be executed concurrently by a thread or ExecutorService.

Callable Declaration:

public interface Callable{
public object call() throws Exception;
}

Runnable Declaration:

public interface Runnable{
public void run();
}

The main difference between the two is that the call() method can return an object from the method call. And call() method can throw an exception while run() method cannot.

cancel task

You can cancel the task submitted to ExecutorService by simply calling the cancel method on the future submitted when the task is submitted.

future.cancel();

ExecutorService Shutdown

In order to keep the threads from running even after the execution is complete, you should shut down the ExecutorService.

shutdown()

To terminate the threads inside an ExecutorService you can call the shutdown() method.

executorService.shutdown();

This brings us to the end of this article where we have learned how we can use ExecutorService to execute tasks in a thread. I hope you are clear with all that has been shared with you in this tutorial.

If you found this article on “ExecutorService in Java” relevant, check out the Edureka Java Course, a trusted online learning company with a network of more than 250,000 satisfied learners spread across the globe. 

We are here to help you with every step on your journey and come up with a curriculum that is designed for students and professionals who want to be a Java Developer. The course is designed to give you a head start into Java programming and train you for both core and advanced Java concepts along with various Java frameworks like Hibernate & Spring.

If you come across any questions, feel free to ask all your questions in the comments section of “ExecutorService in Java” and our team will be glad to answer.

Upcoming Batches For Java Course Online
Course NameDateDetails
Java Course Online

Class Starts on 1st March,2025

1st March

SAT&SUN (Weekend Batch)
View Details
BROWSE COURSES
REGISTER FOR FREE WEBINAR Building Robust Applications with Spring Framework