Java Reference
In-Depth Information
server crash if the traffic load ever reaches a certain threshold. For a server application that
is supposed to provide high availability and graceful degradation under load, this is a serious
failing.
6.2. The Executor Framework
Tasks are logical units of work, and threads are a mechanism by which tasks can run asyn-
chronously. We've examined two policies for executing tasks using threads—execute tasks
sequentially in a single thread, and execute each task in its own thread. Both have serious
limitations: the sequential approach suffers from poor responsiveness and throughput, and the
thread-per-task approach suffers from poor resource management.
In Chapter 5 , we saw how to use bounded queues to prevent an overloaded application from
running out of memory. Thread pools offer the same benefit for thread management, and
java.util.concurrent provides a flexible thread pool implementation as part of the
Executor framework. The primary abstraction for task execution in the Java class libraries
is not Thread , but Executor , shown in Listing 6.3 .
Listing 6.3. Executor Interface.
Executor may be a simple interface, but it forms the basis for a flexible and powerful
framework for asynchronous task execution that supports a wide variety of task execution
policies. It provides a standard means of decoupling task submission from task execution ,
describing tasks with Runnable . The Executor implementations also provide lifecycle
support and hooks for adding statistics gathering, application management, and monitoring.
Executor is based on the producer-consumer pattern, where activities that submit tasks are
the producers (producing units of work to be done) and the threads that execute tasks are the
consumers (consuming those units of work). Usingan Executor isusually theeasiest path
to implementing a producer-consumer design in your application.
Search WWH ::




Custom Search