In §24.3, "Creating Tasks and Threads," you learned how to declare a task class by implementing java.lang.Runnable , and how to create a thread to run a task like this:
Runnable task = new TaskClass(task); new Thread(task).start();
This approach is convenient for a single task execution, but it is not efficient for a large number of tasks, because you have to create a thread for each task. Starting a new thread for each task could limit throughput and cause poor performance. A thread pool is ideal to manage the number of tasks executing concurrently. JDK 1.5 uses the Executor interface for executing tasks in a thread pool and the ExecutorService interface for managing and controlling tasks. ExecutorService is a subinterface of Executor , as shown in Figure 24.8.
To create an Executor object, use the static methods in the Executors class, as shown in Figure 24.9. The newFixedThreadPool(int) method creates a fixed number of threads in a pool. If a thread completes executing a task, it can be reused to execute another task. If a thread terminates due to a failure prior to shutdown, a new thread will be created to replace it if all the threads in the pool are not idle and there are tasks waiting for execution. The newCachedThreadPool() method creates a new thread if all the threads in the pool are not idle and there are tasks waiting for execution. A thread in a cached pool will be terminated if it has not been used for 60 seconds. A cached pool is efficient for many short tasks.
Listing 24.6 shows how to rewrite Listing 24.1, TaskThreadDemo.java, using a thread pool.
1 import java.util.concurrent.*; 2 3 public class ExecutorDemo { 4 public static void main(String[] args) { 5 // Create a fixed thread pool with maximum three threads 6 ExecutorService executor = Executors.newFixedThreadPool( 3 ); 7 8 // Submit runnable tasks to the executor 9 executor.execute( new PrintChar( 'a' , 100 )); 10 executor.execute( new PrintChar( 'b' , 100 ) ); 11 executor.execute( new PrintNum( 100 ,) ); 12 13 // Shutdown the executor 14 executor.shutdown(); 15 } 16 } |
Line 6 creates a thread pool executor with three threads maximum. Classes PrintChar and PrintNum were declared in TaskThreadDemo.java in Listing 24.1. Line 9 creates a task new PrintChar('a', 100) and adds it to the pool. Another two runnable tasks are created and added to the same pool in lines 10 “11. The executor creates three threads to execute three tasks concurrently. What will happen if you replace line 6 by
ExecutorService executor = Executors.newFixedThreadPool( 1 );
The three runnable tasks will be executed sequentially, because there is only one thread in the pool.
What will happen if you replace line 6 by
ExecutorService executor = Executors.newCachedThreadPool();
New threads will be created for each waiting task, so all the tasks will be executed concurrently.
The shutdown() method in line 14 tells the executor to shut down. No new tasks can be accepted, but the existing task will continue to finish.
Tip
If you need to create a thread for one task, use the Thread class. If you need to create threads for multiple tasks, it is better to use a thread pool. |