Demonstrate Executor Service

Overview
We encounter implementations where one main method calls multiple sub-methods (internal/external to current program) in a sequence and wait for the completion of all the methods summing up the total execution time equal to sum of execution times of individual methods. Assuming all the sub-methods are independent and doesn’t need any hierarchy of execution, java concurrency API can used to process all the sub-method calls in parallel there by reducing the execution time nearly equivalent to just longest sub method execution time.

Possible processing options:

  • Processing via for loop.
  • Processing using Executor service.

Technical overview:

  • ExecutorService:
    • ExecutorService is an interface which exposes methods, which is capable of processing the tasks asynchronously. ExecutorService is represents ThreadPool implementation and which is actually an abstraction of ThreadPool.
    • The submit method is used to submit Callable and Runnable tasks for asynchronous process.
    • The shutdown need to be called after processing, in order to reclaim all the resources.
    • Refer ExecutorService javadocs for details.
  • Executors:
  • Callable:
  • Futures:
    • The result of asynchronous computation is represented by Futures.
    • The get method is used to get the result of futures which is synchronous in nature.
    • Java 8 has CompletableFuture which supports asynchronous callback operation.
    • Refer CompletableFuture Javadocs for details.

Source Code Snippets

The code snippet below has below implementations.

  • Creation of Custom Callable.
  • Create a method which mimics external call and wait for 2 secs
  • Call the external call method via conventional java for loop 4 times and check the time taken.
  • Create a thread pool of four threads via ExecutorService and execute external call method in parallel to check the completion time.

 

package com.siva.mythoughts.executorservice;

public class DemonstrateExecutorService {

public static void main(String[] args) {

DemonstrateExecutorService demonstrateExecutorService = new DemonstrateExecutorService();

long startConcurrProcess = System.currentTimeMillis();

// Creates thread pool with four threads
// You can change the number of tests and re-run the program to notice in difference of execution time
ExecutorService executorService = Executors.newFixedThreadPool(4);
List<Future<Integer>> futures = new ArrayList<Future<Integer>>();

for (int i = 0; i < 4; i++) {
DemonstrateExecutorService.CustomCallable callable = demonstrateExecutorService.new CustomCallable(i);
// ExecutorService submit method accepts instance of Callable/Runnable. Use Callable when needs some output
// ExecutorService submit method returns Future instance
futures.add(executorService.submit(callable));
}

// if its not shutdown, hanging threads may effect shutdown of jvm
executorService.shutdown();
while (executorService.isTerminated()) {
// wait till the process is completed
}
for (Future<Integer> future : futures) {
:::
future.get();
:::
}

// Excecution via standard for loop
for (int i = 0; i < 4; i++) {
demonstrateExecutorService.mimicExternalSystemCall(i);
}
}

private class CustomCallable implements Callable<Integer> {

public Integer call() {
return mimicExternalSystemCall(input);
}
}

private int mimicExternalSystemCall(int i) {
::::
Thread.sleep(2000);
::::
}
}

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s