Thread Executors

Exclusive offer: get 50% off this eBook here
Java 7 Concurrency Cookbook

Java 7 Concurrency Cookbook — Save 50%

Over 60 simple but incredibly effective recipes for mastering multithreaded application development with Java 7 with this book and e-book

$29.99    $15.00
by Javier Fernández González | December 2012 | Cookbooks Enterprise Articles Java Oracle

This article by Javier Fernández González, author of Java 7 Concurrency Cookbook, will teach the readers to delegate the thread management to executors. They allow running, managing, and getting the results of concurrent tasks.

(For more resources related to this topic, see here.)

Creating a thread executor

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 recipe, you will learn how these two operations implement an example that will simulate a web server processing requests from various clients.

Getting ready

You can compare both mechanisms and select the best one depending on the problem.

The example of this recipe has been implemented using the Eclipse IDE. If you use Eclipse or other IDE such as NetBeans, open it and create a new Java project.

How to do it...

Follow these steps to implement the example:

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

    public class Task implements Runnable {

  2. Declare a Date attribute named initDate to store the creation date of the task and a String attribute named name to store the name of the task.

    private Date initDate; private String name;

  3. Implement the constructor of the class that initializes both attributes.

    public Task(String name){ initDate=new Date(); this.name=name; }

  4. Implement the run() method.

    @Override public void run() {

  5. First, write to the console the initDate attribute and the actual date, which is the starting date of the task.

    System.out.printf("%s: Task %s: Created on: %s\n",Thread. currentThread().getName(),name,initDate); System.out.printf("%s: Task %s: Started on: %s\n",Thread. currentThread().getName(),name,new Date());

  6. Then, put the task to sleep for a random period of time.

    try { Long duration=(long)(Math.random()*10); System.out.printf("%s: Task %s: Doing a task during %d seconds\n",Thread.currentThread().getName(),name,duration); TimeUnit.SECONDS.sleep(duration); } catch (InterruptedException e) { e.printStackTrace(); }

  7. Finally, write to the console the completion date of the task.

    System.out.printf("%s: Task %s: Finished on: %s\n",Thread. currentThread().getName(),name,new Date());

  8. Now, implement the Server class that will execute every task it receives using an executor. Create a class named Server.

    public class Server {

  9. Declare a ThreadPoolExecutor attribute named executor.

    private ThreadPoolExecutor executor;

  10. Implement the constructor of the class that initializes the ThreadPoolExecutor object using the Executors class.

    public Server(){ executor=(ThreadPoolExecutor)Executors.newCachedThreadPool(); }

  11. Implement the executeTask() method. It receives a Task object as a parameter and sends it to the executor. First, write a message to the console indicating that a new task has arrived.

    public void executeTask(Task task){ System.out.printf("Server: A new task has arrived\n");

  12. Then, call the execute() method of the executor to send it the task.

    executor.execute(task);

  13. Finally, write some executor data to the console to see its status.

    System.out.printf("Server: Pool Size: %d\n",executor. getPoolSize()); System.out.printf("Server: Active Count: %d\n",executor. getActiveCount()); System.out.printf("Server: Completed Tasks: %d\n",executor. getCompletedTaskCount());

  14. Implement the endServer() method. In this method, call the shutdown() method of the executor to finish its execution.

    public void endServer() { executor.shutdown(); }

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

    public class Main { public static void main(String[] args) { Server server=new Server(); for (int i=0; i<100; i++){ Task task=new Task("Task "+i); server.executeTask(task); } server.endServer(); } }

How it works...

The key of this example is the Server 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.

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.

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

  • getPoolSize(): This method returns the actual number of threads in the pool of the executor

  • getActiveCount(): This m ethod 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:

When the last task arrives to the server, the executor has a pool of 100 tasks and 97 active threads.

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.

The ThreadPoolExecutor class also provides other methods related with the finalization of the executor. These methods are:

  • 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 m ethod 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 m ethod 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.

If you want to wait for the completion of the tasks, regardless of their duration, use a big timeout, for example, DAYS.

Java 7 Concurrency Cookbook Over 60 simple but incredibly effective recipes for mastering multithreaded application development with Java 7 with this book and e-book
Published: October 2012
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

Executing tasks in an executor that returns a result

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.

In this recipe, you will learn how to implement tasks that return a result and run them on an executor.

Getting ready...

The example of this recipe has been implemented using the Eclipse IDE. If you use Eclipse or other IDE such as NetBeans, open it and create a new Java project.

How to do it...

Follow these steps to implement the example:

  1. Create a class named FactorialCalculator. Specify that it implements the Callable interface parameterized with the Integer type.

    public class FactorialCalculator implements Callable<Integer> {

  2. Declare a private Integer attribute called number to store the number that this task will use for its calculations.

    private Integer number;

  3. Implement the constructor of the class that initializes the attribute of the class.

    public FactorialCalculator(Integer number){ this.number=number; }

  4. Implement the call() method. This method returns the factorial of the number attribute of FactorialCalculator.

    @Override public Integer call() throws Exception {

  5. First, create and initialize the internal variables used in the method.

    int result = 1;

  6. If the number is 0 or 1, return 1. Otherwise, calculate the factorial of the number. Between two multiplications, and for educational purposes, put this task to sleep for 20 milliseconds.

    if ((num==0)||(num==1)) { result=1; } else { for (int i=2; i<=number; i++) { result*=i; TimeUnit.MILLISECONDS.sleep(20); } }

  7. Write a message to the console with the result of the operation.

    System.out.printf("%s: %d\n",Thread.currentThread(). getName(),result);

  8. Return the result of the operation.

    return result;

  9. Implement the main class of the example by creating a class named Main and implement the main() method.

    public class Main { public static void main(String[] args) {

  10. Create ThreadPoolExecutor to run the tasks using the newFixedThreadPool() method of the Executors class. Pass 2 as the parameter.

    ThreadPoolExecutor executor=(ThreadPoolExecutor)Executors. newFixedThreadPool(2);

  11. Create a list of Future<Integer> objects.

    List<Future<Integer>> resultList=new ArrayList<>();

  12. Create a random number generator with the Random class.

    Random random=new Random();

  13. Generate 10 new random integers between zero and 10.

    for (int i=0; i<10; i++){ Integer number= random.nextInt(10);

  14. Create a FactorialCaculator object passing this random number as a parameter.

    FactorialCalculator calculator=new FactorialCalculator(number);

  15. Call the submit() method of the executor to send the FactorialCalculator task to the executor. This method returns a Future<Integer> object to manage the task, and eventually get its result.

    Future<Integer> result=executor.submit(calculator);

  16. Add the Future object to the list created before.

    resultList.add(result); }

  17. Create a do loop to monitor the status of the executor.

    do {

  18. First, write a message to the console indicating the number of completed tasks with the getCompletedTaskNumber() method of the executor.

    System.out.printf("Main: Number of Completed Tasks: %d\n",executor.getCompletedTaskCount());

  19. Then, for the 10 Future objects in the list, write a message indicating whether the tasks that it manages have finished or not using the isDone() method.

    for (int i=0; i<resultList.size(); i++) { Future<Integer> result=resultList.get(i); System.out.printf("Main: Task %d: %s\n",i,result. isDone()); }

  20. Put the thread to sleep for 50 milliseconds.

    try { TimeUnit.MILLISECONDS.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); }

  21. Repeat this loop while the number of completed tasks of the executor is less than 10.

    } while (executor.getCompletedTaskCount()<resultList.size());

  22. Write to the console the results obtained by each task. For each Future object, get the Integer object returned by its task using the get() method.

    System.out.printf("Main: Results\n"); for (int i=0; i<resultList.size(); i++) { Future<Integer> result=resultList.get(i); Integer number=null; try { number=result.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); }

  23. Then, print the number to the console.

    System.out.printf("Main: Task %d: %d\n",i,number); }

  24. Finally, call the shutdown() method of the executor to finalize its execution.

    executor.shutdown();

How it works...

In this recipe, you 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 critical 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.

Running a task in an executor after a delay

The Executor framework provides the ThreadPoolExecutor class to execute Callable and Runnable tasks with a pool of threads, which avoid you all the thread creation operations. When you send a task to the executor, it's executed as soon as possible, according to the configuration of the executor. There are used cases when you are not interested in executing a task as soon as possible. You may want to execute a task after a period of time or to execute a task periodically. For these purposes, the Executor framework provides the ScheduledThreadPoolExecutor class.

In this recipe, you will learn how to create ScheduledThreadPoolExecutor and how to use it to schedule execution of a task after a given period of time.

Getting ready

The example of this recipe has been implemented using the Eclipse IDE. If you use Eclipse or other IDE such as NetBeans, open it and create a new Java project.

How to do it...

Follow these steps to implement the example:

  1. Create a class named Task that implements the Callable interface parameterized with the String class.

    public class Task implements Callable<String> {

  2. Declare a private String attribute named name that will store the name of the task.

    private String name;

  3. Implement the constructor of the class that initializes the name attribute.

    public Task(String name) { this.name=name; }

  4. Implement the call() method. Write a message to the console with the actual date and return a text, for example, Hello, world.

    public String call() throws Exception { System.out.printf("%s: Starting at : %s\n",name,new Date()); return "Hello, world"; }

  5. Implement the main class of the example by creating a class named Main and add the main() method to it.

    public class Main { public static void main(String[] args) {

  6. Create an executor of the ScheduledThreadPoolExecutor class using the newScheduledThreadPool() method of the Executors class passing 1 as a parameter.

    ScheduledThreadPoolExecutor executor=(ScheduledThreadPoolExecu tor)Executors.newScheduledThreadPool(1);

  7. Initialize and start a few tasks (five in our case) with the schedule() method of the ScheduledThreadPoolExecutor instance.

    System.out.printf("Main: Starting at: %s\n",new Date()); for (int i=0; i<5; i++) { Task task=new Task("Task "+i); executor.schedule(task,i+1 , TimeUnit.SECONDS); }

  8. Request the finalization of the executor using the shutdown() method.

    executor.shutdown();

  9. Wait for the finalization of all the tasks using the awaitTermination() method of the executor.

    try { executor.awaitTermination(1, TimeUnit.DAYS); } catch (InterruptedException e) { e.printStackTrace(); }

  10. Write a message to indicate the time when the program finishes.

    System.out.printf("Main: Ends at: %s\n",new Date());

How it works...

The key point of this example is the Main class and the management of ScheduledThreadPoolExecutor. As with class ThreadPoolExecutor, to create a scheduled executor, Java recommends the utilization of the Executors class. In this case, you have to use the newScheduledThreadPool() method. You have passed the number 1 as a parameter to this method. This parameter is the number of threads you want to have in the pool.

To execute a task in this scheduled executor after a period of time, you have to use the schedule() method. This method receives the following three parameters:

  • The task you want to execute

  • The period of time you want the task to wait before its execution

  • The unit of the period of time, specified as a constant of the TimeUnit class

In this case, each task will wait for a number of seconds (TimeUnit.SECONDS) equal to its position in the array of tasks plus one.

If you want to execute a task at a given time, calculate the difference between that date and the current date and use that difference as the delay of the task.

The following screenshot shows the output of an execution of this example:

You can see how the tasks start their execution one per second. All the tasks are sent to the executor at the same time, but each one with a delay of 1 second later than the previous task.

There's more...

You can also use the Runnable interface to implement the tasks, because the schedule() method of the ScheduledThreadPoolExecutor class accepts both types of tasks.

Although the ScheduledThreadPoolExecutor class is a child class of the ThreadPoolExecutor class and, therefore, inherits all its features, Java recommends the utilization of ScheduledThreadPoolExecutor only for scheduled tasks.

Finally, you can configure the behavior of the ScheduledThreadPoolExecutor class when you call the shutdown() method and there are pending tasks waiting for the end of their delay time. The default behavior is that those tasks will be executed despite the finalization of the executor. You can change this behavior using the setExecuteExistingDelayedTasksAfterShutdownPolicy() method of the ScheduledThreadPoolExecutor class. With false, at the time of shutdown(), pending tasks won't get executed.

Summary

In this article, we have seen how to create threads, how to execute tasks in an executor that return a result, and how to run a task in an executor after delay.

Resources for Article :


Further resources on this subject:


Java 7 Concurrency Cookbook Over 60 simple but incredibly effective recipes for mastering multithreaded application development with Java 7 with this book and e-book
Published: October 2012
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

About the Author :


Javier Fernández González

Javier Fernández González is a software architect with over 10 years experience with Java technologies. He has worked as a teacher, researcher, programmer, analyst, and now as an architect in all types of projects related to Java, especially J2EE. As a teacher, he has taught over 1,000 hours of training in basic Java, J2EE, and Struts framework. As a researcher, he has worked in the field of information retrieval, developing applications for processing large amount of data in Java and has participated as a co-author on several journal articles and conference presentations. In recent years, he has worked on developing J2EE web applications for various clients from different sectors (public administration, insurance, healthcare, transportation, and so on). He currently works as a software architect at Capgemini developing and maintaining applications for an insurance company.

Books From Packt


Java 7 JAX-WS Web Services
Java 7 JAX-WS Web Services

Java 7 New Features Cookbook
Java 7 New Features Cookbook

Oracle Certified Associate, Java SE 7 Programmer Study Guide
Oracle Certified Associate, Java SE 7 Programmer Study Guide

JavaFX 1.2 Application Development Cookbook
JavaFX 1.2 Application Development Cookbook

DWR Java AJAX Applications
DWR Java AJAX Applications

Java EE Development with Eclipse
Java EE Development with Eclipse

Java EE 6 Development with NetBeans 7
Java EE 6 Development with NetBeans 7

Google App Engine Java and GWT Application Development
Google App Engine Java and GWT Application Development


No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
a
B
v
n
M
6
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software