Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Building Multithreaded Java Applications : Page 2

The Java concurrency utilities released in Java 5.0 simplified the development of multithreaded applications through their simple-to-use but robust and powerful API.


Developing a Concurrent Java Application

The sections to follow demonstrate how to use the Java concurrency utility API to develop a multithreaded e-commerce application that processes orders placed online. After the application validates and authorizes orders, it places them in the order-processing queue (java.util.concurrent.BlockingQueue). A pool of order-processor threads polls the order queue continuously and processes the orders when they become available.

Decoupling the application's order-processing code provides the flexibility to increase or decrease the order-processing rate by changing the thread pool size. Putting order objects in a concurrent BlockingQueue ensures that a particular order is processed by only one processor, and it takes care of synchronization automatically.

The code snippets in the upcoming sections are taken from the application source code that accompanies this article.

Extending ThreadPoolExecutor

The Executor interface defines only one method and decouples task submission from how the task will be run. The ExecutorService sub-interface defines additional methods for submitting and tracking asynchronous tasks, as well as shutting down the thread pool. The ThreadPoolExecutor class is a concrete implementation of the ExecutorService interface, which should be sufficient for most of the order-processing application's requirements.

ThreadPoolExecutor also provides useful hookup methods (e.g., beforeExecute), which can be overridden for customization purposes. The CustomThreadPoolExecutor class in Listing 1 extends the ThreadPoolExecutor class and overrides the beforeExecute, afterExecute, and terminated methods.

@Override public void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); Logger.log("After calling afterExecute() method for a thread " + r); } @Override public void terminated() { super.terminated(); Logger.log("Threadpool terminated"); }

The overridden methods simply log the messages, but in a real-world scenario, they can do useful things. For example, the terminated method can send an alert that all the threads in this pool are dead. To properly nest the multiple overrides, you should generally call the superclass's overridden methods from the respective methods in the subclass.

The Java concurrency API also provides the ScheduledExecutorService interface, which extends ExecutorServiceInterface and can schedule the tasks to run after a particular delay or to execute periodically. ScheduledExecutorThreadPool is a concrete implementation of this interface.

Comment and Contribute





