Executor and ExecutorService framework in java - Detailed explanation with full program



In this thread concurrency tutorial we will learn what is java.util.concurrent.Executor and java.util.concurrent.ExecutorService framework in java with program and examples. We will learn how to use Executor and ExecutorService framework in thread concurrency in java. We will learn important methods of Executor like execute and methods of ExecutorService like submit, awaitTermination and shutdown in java. We will also learn what are java.util.concurrent.Future and java.util.concurrent.Callable in java.

Contents of page :
  • 1) java.util.concurrent.Executor in java
    • 1.1) Executor methods in java >
      • void execute(Runnable command)
  • 2) java.util.concurrent.ExecutorService >
    • 2.1) ExecutorService methods >
      • boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException
      • <T> Future<T> submit(Callable<T> task)
      • void shutdown();
      • List<Runnable> shutdownNow()
      • boolean isTerminated()
      • <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException

  • 3) Example/Program to demonstrate usage of Executor and ExecutorService>
  • 3.1) Let’s discuss output in detail, to get better understanding of Executor and ExecutorService usage in program >

  • 4) java.util.concurrent.Future<V> in java
    • V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
    • V get() throws InterruptedException, ExecutionException
    • cancel method
  • 5) java.util.concurrent.Callable<V> in java
    • V call() throws Exception;
    • How Callable and Future are related?
  • 6) Example/Program to demonstrate usage of Callable and Future in java>
  • 7) Similarity and differences between java.util.concurrent.Callable and  java.lang.Runnable in java?
  • 8) Using <T> Future<T> submit(Runnable task, T result) and Future<?> submit(Runnable task) in program in java >
  • 9) Differences between execute() and submit() method of executor framework in java >


Executor and ExecutorService are used for  following purposes in java >
Executor creates pool of threads and manages life cycle of all threads in it in java.

1) What is java.util.concurrent.Executor in java >
java.util.concurrent.Executor interface defines very important execute() method which executes command in java.

1.1) Executor methods in java >
void execute(Runnable command)
Executes the given command. Executor may execute command in a
  • new thread, or
  • in a pooled thread, or
  • in the calling thread
at the discretion of the Executor implementation in java.


2) java.util.concurrent.ExecutorService in java >
java.util.concurrent.ExecutorService interface extends Executor interface in java.
An Executor interface provides following type of methods in java >
  • methods for managing termination and
  • methods that can produce a Future for tracking progress of tasks.

An Executor that provides methods to manage termination and methods that can produce a Future for tracking progress of one or more asynchronous tasks in java.

2.1) ExecutorService methods in java >

boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException
Blocks until one of the following things happen >
  • all tasks have completed execution after a shutdown request, or
  • specified timeout elapses, or
  • current thread is interrupted.


<T> Future<T> submit(Callable<T> task)
Submits a task for execution.
Method returns a Future which represents pending results of the task.
Once task is completed Future's get method will return the task's result.

<T> Future<T> submit(Runnable task, T result)
Submits a Runnable task for execution.
Method returns a Future which represents that task. Once task is completed Future's get method will return result.

Future<?> submit(Runnable task)
Submits a Runnable task for execution.
Method returns a Future which represents that task. Once task is completed Future's get method will return null in java.

void shutdown()
Initiates shutdown of executor, previously submitted tasks are executed, but no new tasks will be accepted in java.

List<Runnable> shutdownNow()
  • executor shutDowns immediately,  
  • all actively executing tasks are stopped,
  • awaiting tasks will never execute, and
  • method returns list all tasks that were awaiting execution in java.

boolean isTerminated()
Method returns true if all tasks have completed following shut down in java.

<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException
Executes the given tasks and returns a list of Futures holding their status in java.


3) Example/Program to demonstrate usage of java.util.concurrent.Executor and java.util.concurrent.ExecutorService in thread concurrency in java >

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class MyRunnable implements Runnable {
   int taskNumber;
   MyRunnable(int taskNumber) {
          this.taskNumber = taskNumber;
   }
   @Override
   public void run() {
          System.out.println(Thread.currentThread().getName()
                       + " executing task no " + taskNumber);
          try {
                 Thread.sleep(1000);
          } catch (InterruptedException e) {
                 e.printStackTrace();
          }
   }
}


/** Copyright (c), AnkitMittal JavaMadeSoEasy.com */
public class ExecutorServiceExample {
   //nThreads number of threads will be created and started in executor.
   //here we will create 2 threads.
   private static int nThreads = 2;
  
   //nTasks number of tasks will be executed.
   //here we will execute 10 tasks.
   private static int nTasks = 10;
   public static void main(String[] args) {
          ExecutorService executor = Executors.newFixedThreadPool(nThreads);
          System.out.println("executor created with 2 threads.");
         
          System.out.println("2 threads in executor will be used for executing 10 tasks. "
                       + "So, at a time only 2 tasks will be executed");
          for (int i = 1; i <= nTasks; i++) {
                 Runnable task = new MyRunnable(i);
                 executor.execute(task);
          }
          /*
          * Initiates shutdown of executor, previously submitted tasks are
          * executed, but no new tasks will be accepted.
          */
          executor.shutdown();
          System.out.println("executor has been shutDown.");
   }
}
/*OUTPUT
executor created with 2 threads.
2 threads in executor will be used for executing 10 tasks. So, at a time only 2 tasks will be executed
pool-1-thread-1 executing task no 1
pool-1-thread-2 executing task no 2
executor has been shutDown.
pool-1-thread-1 executing task no 3
pool-1-thread-2 executing task no 4
pool-1-thread-1 executing task no 5
pool-1-thread-2 executing task no 6
pool-1-thread-1 executing task no 7
pool-1-thread-2 executing task no 8
pool-1-thread-2 executing task no 9
pool-1-thread-1 executing task no 10
*/



3.1) Let’s discuss output in detail, to get better understanding of Executor and ExecutorService usage in program in java >
Note : I have mentioned output in green text.

executor created with 2 threads.
ExecutorService executor = Executors.newFixedThreadPool(nThreads), creates
2 threads in executor.

2 threads in executor will be used for executing 10 tasks. So, at a time only 2 tasks will be executed
2 created threads in executor will be used for executing 10 tasks. So, at a time only 2 tasks will be executed.

pool-1-thread-1 executing task no 1
pool-1-thread-2 executing task no 2
executor has been shutDown.
executor.shutdown(), was called but all previously submitted tasks will be executed.

pool-1-thread-1 executing task no 3
pool-1-thread-2 executing task no 4
pool-1-thread-1 executing task no 5
pool-1-thread-2 executing task no 6
pool-1-thread-1 executing task no 7
pool-1-thread-2 executing task no 8
pool-1-thread-2 executing task no 9
pool-1-thread-1 executing task no 10

If we analyze output at runtime we will notice that at a time only 2 tasks were executed.

We must shutdown executor after executing tasks.


So far in this thread concurrency tutorial we have learned what is Executor and ExecutorService framework in java with program and examples. Now we will learn what are Future and Callable in java.


4) java.util.concurrent.Future<V> in java
Future interface provides methods in java >
  • for returning result of computation, wait until computation is not completed and
  • for cancelling the computation in between in java.

Future Methods in java >

V get() throws InterruptedException, ExecutionException;
Method returns the result of computation, method waits for computation to complete.

V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
Method waits for at most timeout time for computation to complete, and then returns the result, if available.

cancel method
method cancels the task.


5) java.util.concurrent.Callable<V> in java
Callable interface provides method for computing a result and returning that computed result or throws an exception if unable to do so
Any class implementing Callable interface must override call() method.

what type of results Callable’s call() method can return in java?
The Callable<V> is a generic interface, so its call method can return generic result spcified by V.


V call() throws Exception;
method for computing a result.
Method returns computed result or throws an exception if unable to do so.


How Callable and Future are related in java?
If you submit a Callable object to an Executor returned object is of Future type.

Future<Double> futureDouble=executor.submit(new SquareDoubleCallable(2.2));

This Future object can check the status of a Callable call’s method and wait until Callable’s call() method is not completed.

SquareDoubleCallable is a class which implements Callable.


6) Example/Program to demonstrate usage of java.util.concurrent.Callable and java.util.concurrent.Future in thread concurrency in java >
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;
class SumIntegerCallable implements Callable<Integer> {
   Integer n;
   SumIntegerCallable(Integer n) {
          this.n = n;
   }
   @Override
   public Integer call() throws Exception {
          Integer sum = 0;
          for (int i = 0; i <= n; i++) {
                 sum += i;
          }
          return sum;
   }
}
class SquareDoubleCallable implements Callable<Double> {
   Double n;
   SquareDoubleCallable(Double n) {
          this.n = n;
   }
   @Override
   public Double call() throws Exception {
          return n*n;
   }
}
public class CallableFutureExample {
 private static final int NTHREDS = 10;
 public static void main(String[] args) throws InterruptedException, ExecutionException {
   ExecutorService executor = Executors.newFixedThreadPool(NTHREDS);
   Future<Integer> futureInteger=executor.submit(new SumIntegerCallable(4));
   Future<Double> futureDouble=executor.submit(new SquareDoubleCallable(2.2));
  
   System.out.println("SumIntegerCallable has returned > "+futureInteger.get());
   System.out.println("SquareDoubleCallable has returned > "+futureDouble.get());
       
   executor.shutdown();
 }
}
/*OUTPUT
SumIntegerCallable has returned > 10
SquareDoubleCallable has returned > 4.840000000000001
*/

In the above program - we submit a Callable object to an Executor and returned object was of Future type.


7) Similarity and differences between java.util.concurrent.Callable and  java.lang.Runnable in java?

Similarity between java.util.concurrent.Callable and  java.lang.Runnable?
Instances of class which implements callable are executed by another thread.

Difference between java.util.concurrent.Callable and  java.lang.Runnable?
Class implementing Callable interface must override call() method. call() method returns computed result or throws an exception if unable to do so.
Class implementing Runnable interface must override run() method.
A Runnable does not return a result and can neither throw a checked exception.


8) Using <T> Future<T> submit(Runnable task, T result) and Future<?> submit(Runnable task) in program in java >

Let me brief you about both methods again-

<T> Future<T> submit(Runnable task, T result)
Submits a Runnable task for execution. Method returns a Future which represents that task. Once task is completed Future's get method will return the given result.

Future<?> submit(Runnable task)
Submits a Runnable task for execution. Method returns a Future which represents that task. Once task is completed Future's get method will return null.

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
class MyRunnable implements Runnable {
   @Override
   public void run() {
          System.out.println("MyRunnable's run()");
         
   }
}
public class SubmitRunnableExample {
 private static final int NTHREDS = 10;
 public static void main(String[] args) throws InterruptedException, ExecutionException {
   ExecutorService executor = Executors.newFixedThreadPool(NTHREDS);
   Future<Integer> futureInteger=executor.submit(new MyRunnable(), 1);
   System.out.println("futureInteger.get() > "+futureInteger.get());
    
   Future<?> future=executor.submit(new MyRunnable());
   System.out.println("future.get() > "+future.get());
 }
}
/*OUTPUT
MyRunnable's run()
futureInteger.get() > 1
MyRunnable's run()
future.get() > null
*/


Let’s analyze output -
when executor.submit(new MyRunnable(), 1) was called, it internally called call() method and on successful completion of MyRunnable’s run() method, futureInteger.get() returned 1, i.e. second parameter passed in submit method.
This type of submit method could be handy when in certain scenarios we want to return status of task.

when executor.submit(new MyRunnable()) was called, it internally called call() method and on successful completion of MyRunnable’s run() method, futureInteger.get() returned null.
    




9) Differences between execute() and submit() method of executor framework in thread concurrency in java >

execute() method
submit() method
execute() method is defined in Executor interface in java.
submit() method is defined in ExecutorService interface in java.
It can be used for executing runnable task.
It can be used for executing runnable  task or callable task, submitted callable returns future and Future's get method will return the task's result.
Signature of execute method is  >
void execute(Runnable task)
submit method has 3 forms >
<T> Future<T> submit(Callable<T> task)
Submits a callable task for execution.
Method returns a Future which represents pending results of the task.
Once task is completed Future's get method will return the task's result in java.

<T> Future<T> submit(Runnable task, T result)
Submits a Runnable task for execution.
Method returns a Future which represents that task. Once task is completed Future's get method will return result.

Future<?> submit(Runnable task)
Submits a Runnable task for execution.
Method returns a Future which represents that task. Once task is completed Future's get method will return null in java.


So in this thread concurrency tutorial we learned what is java.util.concurrent.Executor and java.util.concurrent.ExecutorService framework in java with program and examples. We learned important methods of Executor like execute and methods of ExecutorService like submit, awaitTermination and shutdown in java. We learned how to use Executor and ExecutorService framework in thread concurrency in java.
We also learned what are java.util.concurrent.Future and java.util.concurrent.Callable in thread concurrency in java.



Having any doubt? or you you liked the tutorial! Please comment in below section.
Please express your love by liking JavaMadeSoEasy.com (JMSE) on facebook, following on google+ or Twitter.


RELATED LINKS>



Semaphore in thread concurrency>

java.util.concurrent.Semaphore in java

Implementation of custom/own Semaphore in java


Semaphore used for implementing Producer Consumer pattern

Custom Semaphore used for implementing Producer Consumer pattern



java.util.concurrent.locks.Lock and Reentrant Locks >

Locks and ReEntrantLocks in java

Implementation of custom/own Lock and ReEntrantLock in java


ReentrantLock class provides implementation of Lock’s newCondition() method - description and solving producer consumer program using this method



ReadWriteLock and ReentrantReadWriteLock >

ReadWriteLock and ReentrantReadWriteLock in java



java.util.concurrent.CountDownLatch in thread concurrency >

CountDownLatch in java

Implementation of custom/own CountDownLatch in java



java.util.concurrent.CyclicBarrier >

CyclicBarrier in java

Implementation of custom/own CyclicBarrier in java


eEdit
Must read for you :