1. Introduction
Java ExecutorService is a framework which simplifies the creation of ThreadPool in Java and allows the execution of the task concurrently in asynchronous mode. It accepts both Runnable and Callable tasks. Here you will learn how to use ExecutorService
to create a ThreadPool and dispatch the tasks to execute concurrently.
2. Java ExecutorService Implementations
As I mentioned in the introduction that Java ExecutorService is used to create Thread Pool, the implementation provided for ExecutorService
interface is, in fact, a Thread Pool implementation. The ExecutorService
has the following implementation in the java.util.concurrent
package:
3. Creating Java ExecutorService
How to Create or Instantiate ExecutorService depends on the implementation that to use. Below are the 2 different way to create ExecutorService. Easiest of these 2 ways is using Executors
factory method.
- Creating with
Executors
factory methods - Directly creating an ExecutorService
3.1. Creating with Executors factory methods
Below java example shows how to create ExecutorService with Executors factory methods
ExecutorService executorService1 = Executors.newSingleThreadExecutor();
ExecutorService executorService2 = Executors.newFixedThreadPool(15);
ExecutorService executorService3 = Executors.newScheduledThreadPool(15);
The are several other factory methods to create ExecutorService that meet specific use cases. To find the best method for your needs, refer to Oracle’s official documentation.
3.2. Directly creating an ExecutorService
ExecutorService is an interface, an instance of any its implementations can be used. There are several implementations to choose from in the java.util.concurrent package or you can also create your own.
For example, the ThreadPoolExecutor class has a few constructors which can be used to configure an executor service and its internal pool.
ExecutorService executorService =
new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
4. ExecutorService Usage
ExecutorService
can execute Runnable and Callable tasks. There are a few different ways to delegate tasks for execution to an ExecutorService
.
- execute(Runnable)
- submit(Runnable)
- submit(Callable)
- invokeAny()
- invokeAll()
We will also take a look at each of these methods in the following sections.
4.1. execute(Runnable)
The execute()
method returns 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). The Java ExecutorService’s execute(Runnable)
method takes a java.lang.Runnable
object, and executes it asynchronously. Here is an example of executing a Runnable
with an ExecutorService
:
/****************************************************************************************
* Created on 06-2019 Copyright(c) https://kodehelp.com All Rights Reserved.
****************************************************************************************/
package com.kodehelp.java.thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by https://kodehelp.com
* Date: 06/23/2019
*/
public class ExecuteRunnableTaskExample {
public static void main(String[] args) {
//Create thread with ExecutorService's newSingleThreadExecutor method
ExecutorService executor = Executors.newSingleThreadExecutor();
//Notice that Java 8 lambda expressions are used here instead of
//anonymous inner classes.
executor.execute(() -> System.out.println("I'm Runnable task using Java 8+."));
//Before Java 8, you need to pass anonymous inner class as below
executor.execute(new Runnable() {
public void run() {
System.out.println("I'm Runnable task before Java 8.");
}
});
}
}
4.2. submit(Runnable)
The Java ExecutorService submit(Runnable) method also takes a Runnable implementation, but returns a Future object. This Future object is used to check if the Runnable has finished executing. Here is a Java ExecutorService submit() example:
/****************************************************************************************
* Created on 06-2019 Copyright(c) https://kodehelp.com All Rights Reserved.
****************************************************************************************/
package com.kodehelp.java.thread;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* Created by https://kodehelp.com
* Date: 06/23/2019
*/
public class ExecuteRunnableTaskExample {
public static void main(String[] args) {
//Create threads with ExecutorService's newFixedThreadPool method
ExecutorService executor = Executors.newFixedThreadPool(5);
try {
//Notice that Java 8 lambda expressions are used here instead of
//anonymous inner classes.
Future<?> future1 = executor.submit(() -> {
System.out.println("I'm Runnable task using Java 8+.");
});
System.out.println(future1.get());
//Before Java 8, you need to pass anonymous inner class as below
Future<?> future2 = executor.submit(new Runnable() {
public void run() {
System.out.println("I'm Runnable task before Java 8.");
}
});
System.out.println(future2.get());
}catch (InterruptedException e) {// thread was interrupted
e.printStackTrace();
} catch (ExecutionException e) {// thread threw an exception
e.printStackTrace();
} finally {
// shut down the executor manually
executor.shutdown();
}
}
}
4.3. submit(Callable)
The Java ExecutorService submit(Callable)
method is similar to the submit(Runnable)
method except it takes a Java Callable instead of a Runnable. The Callable’s result can be obtained via the Java Future object returned by the submit(Callable)
method. Here is an ExecutorService Callable example:
/****************************************************************************************
* Created on 06-2019 Copyright(c) https://kodehelp.com All Rights Reserved.
****************************************************************************************/
package com.kodehelp.java.thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* Created by https://kodehelp.com
* Date: 06/23/2019
*/
public class ExecuteCallableTaskExample {
/**
* @param args
*/
public static void main(String[] args) {
//Create threads with ExecutorService's newFixedThreadPool method
ExecutorService executor = Executors.newFixedThreadPool(5);
try {
//Notice that Java 8 lambda expressions are used here instead of
//anonymous inner classes.
Future<?> future1 = executor.submit(() -> {
System.out.println("I'm Callable task.");
return 2 + 2;
});
System.out.println(future1.get());
//Before Java 8, you need to pass anonymous inner class as below
Future<?> future2 = executor.submit(new Callable() {
public Integer call() {
System.out.println("I'm Callable task before Java 8.");
return 2 + 2;
}
});
System.out.println(future2.get());
}catch (InterruptedException e) {// thread was interrupted
e.printStackTrace();
} catch (ExecutionException e) {// thread threw an exception
e.printStackTrace();
} finally {
// shut down the executor manually
executor.shutdown();
}
}
}
4.4. invokeAny()
The invokeAny()
method takes a collection of Callable objects, or sub interfaces of Callable. Invoking this method does not return a Future, but returns the result of one of the Callable objects. You will have no guarantee about which of the Callable’s results you get. Just one of the ones that finish. If one of the tasks complete or throws an exception, the rest of the Callable’s are cancelled. Here is the Java ExecutorService example to submit task using invokeAny()
:
/****************************************************************************************
* Created on 06-2019 Copyright(c) https://kodehelp.com All Rights Reserved.
****************************************************************************************/
package com.kodehelp.java.thread;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by https://kodehelp.com
* Date: 06/23/2019
*/
public class InvokeAnyExample {
/**
* @param args
*/
public static void main(String[] args) {
//Create threads with ExecutorService's newFixedThreadPool method
ExecutorService executor = Executors.newFixedThreadPool(2);
try {
//Notice that Java 8 lambda expressions are used here instead of
//anonymous inner classes.
List<Callable> listOfCallable = Arrays.asList(
() -> 1,
() -> 2,
() -> 3);
Integer result = executor.invokeAny(listOfCallable);
System.out.println(result);
}catch (InterruptedException e) {// thread was interrupted
e.printStackTrace();
} catch (ExecutionException e) {// thread threw an exception
e.printStackTrace();
} finally {
// shut down the executor manually
executor.shutdown();
}
}
}
4.5. invokeAll()
The invokeAll()
method invokes all of the Callable objects you pass to it in the collection passed as parameter. The invokeAll()
returns a list of Future objects via which you can obtain the results of the executions of each Callable.
Keep in mind that a task might finish due to an exception, so it may not have “succeeded”. There is no way on a Future to tell the difference.
Here is the Java ExecutorService example for invokeAll() :
/****************************************************************************************
* Created on 06-2019 Copyright(c) https://kodehelp.com All Rights Reserved.
****************************************************************************************/
package com.kodehelp.java.thread;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* Created by https://kodehelp.com
* Date: 06/23/2019
*/
public class InvokeAllExample {
/**
* @param args
*/
public static void main(String[] args) {
//Create threads with ExecutorService's newFixedThreadPool method
ExecutorService executor = Executors.newFixedThreadPool(2);
try {
//Notice that Java 8 lambda expressions are used here instead of
//anonymous inner classes.
List<Callable> listOfCallable = Arrays.asList(
() -> 1,
() -> 2,
() -> 3);
List<Future> futures = executor.invokeAll(listOfCallable);
for(Future future : futures){
System.out.println("future.get = " + future.get());
}
}catch (InterruptedException e) {// thread was interrupted
e.printStackTrace();
} catch (ExecutionException e) {// thread threw an exception
e.printStackTrace();
} finally {
// shut down the executor manually
executor.shutdown();
}
}
}
References: