A thread pool helps to constrain the number of threads that may be running in an application at any one time. As threads require system resources, having too many threads executing simultaneously will negatively impact on a system’s performance.
Threads can be represented as objects. To define what our threads will be doing, we create a class that implements the Callable interface. In this example, the thread will computer an integer. The interface, itself, provides only one method – call. This is the method that is actually executed when the thread is running. Since we have assigned the integer as the generic type in the class definition, the method must also return an integer (see thegenerics guide for information on generics).
import java.util.concurrent.Callable;
2
3 public class ExecAdd implements Callable<Integer>
4 {
5 private int id = 0;
6
7 public ExecAdd (int threadId)
8 {
9 id = threadId;
10 }
11
12 /**
13 * This is the method that will be executed
14 * when the thread is running.
15 */
16 @Override
17 public Integer call() throws Exception
18 {
19 int result = 1;
20 System.out.println("Thread " + id +
21 " calculating …");
22
23 // Compute the result.
24 for (int value = 1; value <= id; value++)
25 {
26 result = result + value;
27 }
28
29 // Delay for a visible amount of time.
30 // This is just for show.
31 try {
32 Thread.sleep(2000);
33 } catch (InterruptedException e) {
34 System.out.println("Interrupted");
35 }
36
37 return result;
38 }
39 }
Note that the call to sleep at line 32 is only intended to make the thread last a bit longer. It will, later, cause the thread pool to fill up and force other threads to wait before executing. The creation of the thread pool in which to execute these threads and the extraction of the return values from them is done in the main method of another class.
import java.util.ArrayList;
3 import java.util.List;
4 import java.util.concurrent.ExecutionException;
5 import java.util.concurrent.ExecutorService;
6 import java.util.concurrent.Executors;
7 import java.util.concurrent.Future;
8
9 public class ThreadCreator {
10 public static void main(String[] args) {
The thread pool Executors class provides several methods for creating different types of thread pools. For this example, the fixed thread pool is used. A fixed thread pool will allow up to a certain number of threads to run at any one time. To show this behaviour, the example uses a thread pool size of ten but will later give thirty threads to the pool to execute.
// Use a thread pool executor to generate 20 // Reference to the results.
21 List<Future<Integer>> allResults = null;
22
12 // the lists. 13 ExecutorService calcExecutor = 14 Executors.newFixedThreadPool(10); 15 16 // Maintains a reference to our adders. 17 ArrayList<ExecAdd> adders = new 18 ArrayList<ExecAdd>(); 19
The use of a list to maintain references to the threads is so that the threads will be started simultaneously (the execution of the threads comes later). When the thread pool finishes executing a thread, the return value from the thread execution is obtained through the Future object.
20 // Reference to the results.
21 List<Future<Integer>> allResults = null;
22
Next, we create the instances of the thirty threads that will be executed in the thread pool.
23 // Create an instance of the calculators
24 // to be executed.
25 for (int index = 0; index < 30; index++)
26 {
27 adders.add(new ExecAdd(index));
28 }
29
To execute the threads, the list of the threads are given to the thread pool.
30 try {
31 // Perform the calculations.
32 allResults = calcExecutor.
33 invokeAll(adders);
34
35 // Output the results.
36 for (Future<Integer> calcResult:
37 allResults)
38 {
39 System.out.println(
40 calcResult.get());
41 }
42
When the get() method is called, the system will wait for the thread to finish execution if it has not finished already and then return the result. All that is left is the handling of the exceptions that can possibly be thrown.'
43 } catch (InterruptedException e) {
44 System.out.println("Interrupted");
45 } catch (ExecutionException e) {
46 System.out.println(
47 "Execution exception");
48 }
49
50 }
51 }
When you execute the code, you should notice a slight pause in between a batch of threads. This is because we have a thread pool of ten that executes at any one time, but we gave it thirty threads!!