Java Concurrency – Part 7 : Executors and thread pools

This entry is part 6 of 7 in the series Java Concurrency Tutorial

Let’s start with a new post in the Java concurrency series.

This time we’ll learn how to start cleanly new threads and to manage thread pools. In Java, if you have a Runnable like this :

Runnable runnable = new Runnable(){
   public void run(){
      System.out.println("Run");
   }
}

You can easily run it in a new thread :

new Thread(runnable).start();

This is very simple and clean, but what if you’ve several long running tasks that you want to load in parralel and then wait for the completion of all the tasks, it’s a little bit harder to code and if you want to get the return value of all the tasks it becomes really difficult to keep a good code. But like for almost any problems, Java has a solution for you, the Executors. This simple class allows you to create thread pools and thread factories.

A thread pool is represented by an instance of the class ExecutorService. With an ExecutorService, you can submit task that will be completed in the future. Here are the type of thread pools you can create with the Executors class :

  • Single Thread Executor : A thread pool with only one thread. So all the submitted task will be executed sequentially. Method : Executors.newSingleThreadExecutor()
  • Cached Thread Pool : A thread pool that create as many threads it needs to execute the task in parralel. The old available threads will be reused for the new tasks. If a thread is not used during 60 seconds, it will be terminated and removed from the pool. Method : Executors.newCachedThreadPool()
  • Fixed Thread Pool : A thread pool with a fixed number of threads. If a thread is not available for the task, the task is put in queue waiting for an other task to ends. Method : Executors.newFixedThreadPool()
  • Scheduled Thread Pool : A thread pool made to schedule future task. Method : Executors.newScheduledThreadPool()
  • Single Thread Scheduled Pool : A thread pool with only one thread to schedule future task. Method : Executors.newSingleThreadScheduledExecutor()

Once you have a thread pool, you can submit task to it using the different submit methods. You can submit a Runnable or a Callableto the thread pool. The method return a Future representing the future state of the task. If you submitted a Runnable, the Future object return null once the task finished.

By example, if you have this Callable :

private final class StringTask implements Callable<String> {
   public String call(){
      //Long operations

      return "Run";
   }
}

If you want to execute that task 10 times using 4 threads, you can use that code :

ExecutorService pool = Executors.newFixedThreadPool(4);

for(int i = 0; i < 10; i++){
   pool.submit(new StringTask());
}

But you must shutdown the thread pool in order to terminate all the threads of the pool :

pool.shutdown();

If you don’t do that, the JVM risk to not shutdown because there is still threads not terminated. You can also force the shutdown of the pool using shutdownNow, with that the currently running tasks will be interrupted and the tasks not started will not be started at all.

But with that example, you cannot get the result of the task. So let’s get the Future objects of the tasks :

ExecutorService pool = Executors.newFixedThreadPool(4);

List<Future<String>> futures = new ArrayList<Future<String>>(10);

for(int i = 0; i < 10; i++){
   futures.add(pool.submit(new StringTask()));
}

for(Future<String> future : futures){
   String result = future.get();

   //Compute the result
}

pool.shutdown();

But this code is a bit complicated. And there is a disadvantage. If the first task takes a long time to compute and all the other tasks ends before the first, the current thread cannot compute the result before the first task ends. Once again, Java has the solution for you, CompletionService.

A CompletionService is a service that make easier to wait for result of submitted task to an executor. The implementation is ExecutorCompletionService who’s based on an ExecutorService to work. So let’s try :

ExecutorService threadPool = Executors.newFixedThreadPool(4);
CompletionService<String> pool = new ExecutorCompletionService<String>(threadPool);

for(int i = 0; i < 10; i++){
   pool.submit(new StringTask());
}

for(int i = 0; i < 10; i++){
   String result = pool.take().get();

   //Compute the result
}

threadPool.shutdown();

With that, you have the result in the order they are completed and you don’t have to keep a collection of Future.

Here we are, you have the tools in hand to launch tasks in parralel using performing thread pools. Using Executors, ExecutorService and CompletionService you can create complex algorithm using several taks. With that tools, it’s really easy to change the number of threads performing in parralel or adding more tasks without changing a lot of code.

I hope that this post will help you to write better concurrent code.

Series Navigation<< Java Concurrency – Part 6 : Atomic Variables
 

  • http://www.fromdev.com Priya

    Interesting post. I would love to see the publisher subscriber impl in this.

  • http://www.fromdev.com Priya

    Interesting post. I would love to see the publisher subscriber impl in this.

  • http://www.soa-at-work.com Eduard Hildebrandt

    Good article! If you are using Spring Framework in you application then I suggest to use the Spring TaskExecutor abstraction.

    • Anonymous

      Hi,

      Thanks for comment.

      I didn’t know this abstraction, I will try it, I use Spring often. Thank you

  • http://www.modularhomesnetwork.com Factory Built Homes

    We are waiting to the new improvements like these soon.

  • Teja

    Nice article. Thank you.

  • Anuta S

    Thank you.

    One note. Callable is interface and should be implemented. So, fix this line:

    private final class StringTask extends Callable{

    • Anonymous

      You’re absolutely right, thank you :)

      I made the correction on the article.

  • Chandana Fit

    Nice article with lot of value

  • Pablo Pera

    Nice post. It ranks pretty high for Java concurrency queries, which is pretty useful actually.

    As a minor improvement, you should use generics for the CompletionService and the Callable. Also, the code is not fully copy-pasteable because of some “<” and the like.

    • wichtounet

      Thank you. 

      As a matter of fast, I was using generics but my WordPress editor decided to strip all the chars and whatever was between them in my code… I did put them again on the samples. 

  • Mrkumarawanish

     Thanks,

    If the same task can be executed by thread, then what should be used thread or ExecutorService. Which is better for performance point of view…?

    • wichtounet

      There are no real performance improvements using ExecutorService. It improves the quality and adaptativity of the code.

      But it is possible that there are some possible performances improvements by using this pool over than a custom pool in a custom list.

  • http://www.facebook.com/makarand.mone Makarand Mone

    Thanks. Just what i needed

  • Sandeep

    Good one. A nice starting point!

    • wichtounet

      Thank you :)

  • Pham Hung Son

    Tks alot, I read your article, playing around with Executors : getting much more confident with concurrency :-)

  • Jay

    Clear and Understandable… thx!

  • Sunny

    Very nice tutorials ..I have read all the 7 parts of it..I am waiting for more :)