Friday, April 3, 2015

newFixedThreadPool, Callable and Future example in Java

In this article, we will learn how to implement tasks that return a result and run them on an executor using Callable and Future interfaces with the help Executor framework. This post is continuation of previous post where we learned about cached Thread pool

One of the advantages of the Executor framework is that you can run concurrent tasks that return a result. The Java Concurrency API achieves this with the following two interfaces:

  • Callable: This interface has the call() method. In this method, you have to implement the logic of a task. The Callable interface is a parameterized interface, meaning you have to indicate the type of data the call() method will return.
  • Future: This interface has some methods to obtain the result generated by a Callable object and to manage its state



Create a class named FactCalculator that implements the Callable interface parameterized with the Integer type



Implement the Main class


Output

  Number of completed task : 0
  Task 0 status : false
  Task 1 status : false
  Task 2 status : false
  Task 3 status : false
  Task 4 status : false
  Task 5 status : false
  Task 6 status : false
  Task 7 status : false
  Task 8 status : false
  Task 9 status : false
  Number of completed task : 1
  Task 0 status : true
  Task 1 status : false
  Task 2 status : false
  Task 3 status : false
  Task 4 status : false
  Task 5 status : false
  Task 6 status : false
  Task 7 status : false
  Task 8 status : false
  Task 9 status : false
  Number of completed task : 2
  Task 0 status : true
  Task 1 status : true
  Task 2 status : true
  Task 3 status : false
  Task 4 status : false
  Task 5 status : false
  Task 6 status : false
  Task 7 status : false
  Task 8 status : false
  Task 9 status : false
  Number of completed task : 3
  Task 0 status : true
  Task 1 status : true
  Task 2 status : true
  Task 3 status : false
  Task 4 status : false
  Task 5 status : false
  Task 6 status : false
  Task 7 status : false
  Task 8 status : false
  Task 9 status : false
  Number of completed task : 3
  Task 0 status : true
  Task 1 status : true
  Task 2 status : true
  Task 3 status : true
  Task 4 status : false
  Task 5 status : false
  Task 6 status : false
  Task 7 status : false
  Task 8 status : false
  Task 9 status : false
  Number of completed task : 4
  Task 0 status : true
  Task 1 status : true
  Task 2 status : true
  Task 3 status : true
  Task 4 status : false
  Task 5 status : false
  Task 6 status : false
  Task 7 status : false
  Task 8 status : false
  Task 9 status : false
  Number of completed task : 4
  Task 0 status : true
  Task 1 status : true
  Task 2 status : true
  Task 3 status : true
  Task 4 status : true
  Task 5 status : false
  Task 6 status : false
  Task 7 status : false
  Task 8 status : false
  Task 9 status : false
  Number of completed task : 6
  Task 0 status : true
  Task 1 status : true
  Task 2 status : true
  Task 3 status : true
  Task 4 status : true
  Task 5 status : false
  Task 6 status : true
  Task 7 status : false
  Task 8 status : false
  Task 9 status : false
  Number of completed task : 6
  Task 0 status : true
  Task 1 status : true
  Task 2 status : true
  Task 3 status : true
  Task 4 status : true
  Task 5 status : true
  Task 6 status : true
  Task 7 status : true
  Task 8 status : false
  Task 9 status : false
  Number of completed task : 8
  Task 0 status : true
  Task 1 status : true
  Task 2 status : true
  Task 3 status : true
  Task 4 status : true
  Task 5 status : true
  Task 6 status : true
  Task 7 status : true
  Task 8 status : false
  Task 9 status : false
  Number of completed task : 8
  Task 0 status : true
  Task 1 status : true
  Task 2 status : true
  Task 3 status : true
  Task 4 status : true
  Task 5 status : true
  Task 6 status : true
  Task 7 status : true
  Task 8 status : false
  Task 9 status : false
  Number of completed task : 8
  Task 0 status : true
  Task 1 status : true
  Task 2 status : true
  Task 3 status : true
  Task 4 status : true
  Task 5 status : true
  Task 6 status : true
  Task 7 status : true
  Task 8 status : false
  Task 9 status : false
  Main result : 
  Result of Task: 0 2
  Result of Task: 1 120
  Result of Task: 2 6
  Result of Task: 3 720
  Result of Task: 4 362880
  Result of Task: 5 362880
  Result of Task: 6 2
  Result of Task: 7 24
  Result of Task: 8 40320
  Result of Task: 9 40320


How it works...
In this example, we have learned how to use the Callable interface to launch concurrent tasks that return a result. You have implemented the FactorialCalculator class that implements the Callable interface with Integer as the type of the result. Hence, it returns before type of the call() method.
The other important point of this example is in the Main class. You send a Callable object to be executed in an executor using the submit() method. This method receives a Callable object as a parameter and returns a Future object that you can use with two main objectives

  • You can control the status of the task: you can cancel the task and check if it has finished. For this purpose, you have used the isDone() method to check if the tasks had finished.
  • You can get the result returned by the call() method. For this purpose, you have used the get() method. This method waits until the Callable object has finished the execution of the call() method and has returned its result. If the thread is interrupted while the get() method is waiting for the result, it throws an InterruptedException exception. If the call() method throws an exception, this method throws an ExecutionException exception.

There's more...
When you call the get() method of a Future object and the task controlled by this object hasn't finished yet, the method blocks until the task finishes. The Future interface provides another version of the get() method.


get(long timeout, TimeUnit unit): This version of the get method, if the result of the task isn't available, waits for it for the specified time. If the specified period of time passes and the result isn't yet available, the method returns a null value. The TimeUnit class is an enumeration with the following constants: DAYS, HOURS, MICROSECONDS, MILLISECONDS, MINUTES, NANOSECONDS, and SECONDS.



That's all. Thanks for reading this and if you found this article useful, I would like to see your appreciation in the form of comments.



If you know anyone who has started learning Java, why not help them out! Just share this post with them. Thanks for studying today!...

Thursday, April 2, 2015

newCachedThreadPool example in Java

The first step to work with the Executor framework is to create an object of the ThreadPoolExecutor class. You can use the four constructors provided by that class or use a factory class named Executors that creates ThreadPoolExecutor. Once you have an executor, you can send Runnable or Callable objects to be executed. 
In this  article, you will learn how these two operations implement an example that will simulate a server processing requests from various clients. Before that you can have an overview of Executor frameworks in my previous article.



First, you have to implement the tasks that will be executed by the server. Create a class named Task that implements the Runnable interface


Now, implement the CachedPoolServer class that will execute every task it receives using an executor


Finally, implement the main class of the example by creating a class named Main and implement the main() method



How it works...
The main part of this example is the CachedPoolServer class. This class creates and uses ThreadPoolExecutor to execute tasks

The first important point is the creation of ThreadPoolExecutor in the constructor of the Server class. The ThreadPoolExecutor class has four different constructors but, due to their complexity, the Java concurrency API provides the Executors class to construct executors and other related objects. Although we can create  threadPoolExecutor directly using one of its constructors, it's recommended to use the Executors class.

In this case, you have created a cached thread pool using the newCachedThreadPool() method. This method returns an ExecutorService object, so it's been cast to ThreadPoolExecutor to have access to all its methods. The cached thread pool you have created creates new threads if needed to execute the new tasks, and reuses the existing ones if they have finished the execution of the task they were running, which are now available. The reutilization of threads has the advantage that it reduces the time taken for thread creation. The cached thread pool has, however, a disadvantage of constant lying threads for new tasks, so if you send too many tasks to this executor, you can overload the system

Tip
Use the executor created by the newCachedThreadPool() method only when you have a reasonable number of threads or when they have a short duration.

Once you have created the executor, you can send tasks of the Runnable or Callable type for execution using the execute() method. In this case, you send objects of  the Task class that implements the Runnable interface.

We also have printed some log messages with information about the executor. Specifically, you have used the following methods:

  • getPoolSize(): This method returns the actual number of threads in the pool of the executor
  • getActiveCount(): This method returns the number of threads that are executing tasks in the executor.
  • getCompletedTaskCount(): This method returns the number of tasks completed by the executor


One critical aspect of the ThreadPoolExecutor class, and of the executors in general, is that you have to end it explicitly. If you don't do this, the executor will continue its execution and the program won't end. If the executor doesn't have tasks to execute, it continues waiting for new tasks and it doesn't end its execution. A Java application won't end until all its non-daemon threads finish their execution, so, if you don't terminate the executor, your application will never end.


To indicate to the executor that you want to finish it, you can use the shutdown() method of the ThreadPoolExecutor class. When the executor finishes the execution of all pending tasks, it finishes its execution. After you call the shutdown() method, if you try to send another task to the executor, it will be rejected and the executor will throw a RejectedExecutionException exception. The following screenshot shows part of one execution of this example:




There's more...
The ThreadPoolExecutor class provides a lot of methods to obtain information about its status. We used in the example the getPoolSize(), getActiveCount(), and getCompletedTaskCount() methods to obtain information about the size of the pool, the number of threads, and the number of completed tasks of the executor. You can also use the getLargestPoolSize() method that returns the maximum number of threads that has been in the pool at a time.

  • shutdownNow(): This method shut downs the executor immediately. It doesn't execute the pending tasks. It returns a list with all these pending tasks. The tasks that are running when you call this method continue with their execution, but the method doesn't wait for their finalization.
  • isTerminated(): This method returns true if you have called the shutdown() or shutdownNow() methods and the executor finishes the process of shutting it down.
  • isShutdown(): This method returns true if you have called the shutdown() method of the executor.
  • awaitTermination(long timeout, TimeUnit unit): This method blocks the calling thread until the tasks of the executor have ended or the timeout occurs. The TimeUnit class is an enumeration with the following constants: DAYS, HOURS, MICROSECONDS, MILLISECONDS, MINUTES, NANOSECONDS, and SECONDS


That's all. Thanks for reading this and if you found this article useful, I would like to see your appreciation in the form of comments.



If you know anyone who has started learning java, why not help them out! Just share this post with them. Thanks for studying today!...