Build Java Apps that Can Multitask

Build Java Apps that Can Multitask

f you worked with thread programming in C or C++ or prior versions of Java, you know what a headache managing the threads in your code can be. In single-threaded programs, a bug in the code causes an application to fail at the same point each and every time. In multithreaded programs, however, the failure occurs only when certain conditions are met. Because predicting all the conditions that can cause application failure is so difficult, thread programming is challenging. Some programmers avoid the challenge all together, while others?savvy problem-solvers?stay glued to their computers until they get it right.

The J2SE 5.0 platform includes a new package of concurrency utilities. The classes in this package are building blocks for concurrent classes or applications used in concurrent designs. The concurrency utilities include the following:

  • A high-performance, flexible thread pool
  • A framework for asynchronous execution of tasks
  • A host of collection classes optimized for concurrent access

This article introduces the J2SE 5.0 framework classes and their important features. The accompanying downloadable code provides simple and easy-to-use examples that demonstrate all the new thread framework classes. Running the examples while you read the article gives you a better understanding of each feature.

Executor Framework
The Executor framework provides simple standardized extensible classes that offer useful functionality that otherwise is tedious or difficult to implement manually. This framework standardizes invocation, scheduling, and execution. It provides support for controlling asynchronous tasks according to a set of execution policies.

The Executor interface executes submitted runnable tasks. It provides a way to decouple task submission from the mechanics of task execution. Programmers normally use an Executor instead of explicitly creating threads. The Executor interface also offers both synchronous and asynchronous execution of tasks.

For synchronous execution, use the following commands:

Class MySynExecutor implements Executor{	public void execute(Runnable r) {;     	}}

For asynchronous execution, use the following commands:

Class MyASynExecutor implements Executor{	public void execute(Runnable r) {        	new Thread(r).start();     	}}

ExecutorService Class
The ExecutorService class provides methods for managing termination and tracking the progress of one or more asynchronous tasks. The file in the accompanying code download demonstrates the process of managing termination. It initiates a ThreadPool of size three and adds the threads sequentially. When the number of threads reaches the pool size, it invokes the shutdown method. After calling the shutdown() method, the pool does not accept any new tasks for execution. After waiting 10 seconds, the pool invokes shutDownNow(). This method makes a best effort to terminate all running tasks. In the example the application fails to terminate the executing threads.

The ScheduledExecutorService class is my favorite. It is very handy for scheduling tasks that run periodically, which is especially useful for cleanup jobs (e.g., cleaning up all the temp files created by your application, etc.).The file demonstrates the scheduling process by printing beep every five seconds:

final Runnable beeper = new Runnable() {		public void run() { System.out.println("beep"); }};final ScheduledFuture beeperHandle =scheduler.scheduleAtFixedRate(beeper, 1, 5, SECONDS); 

Future and FutureTask
In earlier versions of Java, it is very difficult to find the status of an executing thread and make the thread return a value after execution. Because the run method returns void, you need to write a lot of code to get a return value from the thread. Programmers who tried this approach understand the ordeals associated with it.

Using the Future interface or the FutureTask class you can get a return value from the asynchronous execution of the thread. The Future interface provides methods to check if the computation is complete, retrieve the results of the computation, or cancel the computation. FutureTask provides the basic implementation of the Future interface methods. The results can be retrieved only when the computations have completed; if the computation is not completed, the get method will block.

The file demonstrates the use of the FutureTask class with an easy-to-understand example. It reverses the submitted string slowly at a rate of one char per second. In the mean time, the main thread keeps polling to see if the task is completed:

while(!future.isDone()){ System.out.println("Task not yet completed."); try{	 Thread.currentThread().sleep(500); }catch(InterruptedException ie){ System.out.println("Will check after 1/2 sec."); }}

After the task is completed, the result is retrieved from the Future object using the get method:

System.out.println("Here is result..."+future.get());

With the ThreadPoolExecutor class, you can write your own server. This class provides many features for configuring and tuning it, similar to many large-scale enterprise EJB servers. The following are a few of its configurable parameters:

  • Core and maximum poolsizes

By setting corePoolSize and maximumPoolSize to the same value, you create a fixed-size thread pool. By setting maximumPoolSize to an essentially unbounded value such as Integer.MAX_VALUE, you allow the pool to accommodate an arbitrary number of concurrent tasks.

  • On-demand construction

By default, ThreadPoolExecutor initially creates and starts even core threads only when new tasks need them, but you can override this dynamically using prestartCoreThread or prestartAllCoreThreads.

  • Keep-alive times

If the pool currently has more than corePoolSize threads, excess threads will be terminated if they have been idle for more than the keepAliveTime.

  • Queuing

Queuing follows the following rules:

  • If fewer than corePoolSize threads are running, the Executor always prefers adding a new thread rather than queuing.
  • If corePoolSize or more threads are running, the Executor always prefers queuing a request rather than adding a new thread.
  • If a request cannot be queued, a new thread is created unless this would exceed maximumPoolSize, in which case, the task will be rejected.
  • Hook methods

This class provides beforeExecute() and afterExecute() hook methods that are called before and after execution of each task. In order to use them, you must sub-class the class (as these methods are protected). provides detailed examples to monitor various configured parameters. You can uncomment the code to see for yourself how the pool and queue sizes vary with the addition and completion of each task. You also can play with the value settings in the code.

Concurrent Collections
JDK 1.5 provides the following Collection implementations that are designed for use in multithreaded contexts:

The ConcurrentHashMap class provides full thread-safe concurrency support for retrievals and adjustable expected concurrency for updates. CopyOnWriteArraySet is a thread-safe variant of set, and CopyOnWriteArrayList is a thread-safe variant of ArrayList. Each makes a copy of the underlying array or sets it before modifying the original. As a result, the reads are fast but the updates are slow.

Concurrent collection classes provide snapshot-style data to the Iterators (even when the underlying data is changed, it is not reflected in the Iterators).

JDK 1.5 provides advanced classes like Semaphore, CountDownLatch, CyclicBarrier, and an Exchanger for special-purpose synchronization. A detailed analysis and usage of these classes is beyond the scope of this article, as it requires some academic background.

With this new set of classes, you can convince your thread-scared, technical boss to develop multithreaded applications.

Share the Post:
XDR solutions

The Benefits of Using XDR Solutions

Cybercriminals constantly adapt their strategies, developing newer, more powerful, and intelligent ways to attack your network. Since security professionals must innovate as well, more conventional endpoint detection solutions have evolved

AI is revolutionizing fraud detection

How AI is Revolutionizing Fraud Detection

Artificial intelligence – commonly known as AI – means a form of technology with multiple uses. As a result, it has become extremely valuable to a number of businesses across

AI innovation

Companies Leading AI Innovation in 2023

Artificial intelligence (AI) has been transforming industries and revolutionizing business operations. AI’s potential to enhance efficiency and productivity has become crucial to many businesses. As we move into 2023, several

data fivetran pricing

Fivetran Pricing Explained

One of the biggest trends of the 21st century is the massive surge in analytics. Analytics is the process of utilizing data to drive future decision-making. With so much of

kubernetes logging

Kubernetes Logging: What You Need to Know

Kubernetes from Google is one of the most popular open-source and free container management solutions made to make managing and deploying applications easier. It has a solid architecture that makes

ransomware cyber attack

Why Is Ransomware Such a Major Threat?

One of the most significant cyber threats faced by modern organizations is a ransomware attack. Ransomware attacks have grown in both sophistication and frequency over the past few years, forcing

data dictionary

Tools You Need to Make a Data Dictionary

Data dictionaries are crucial for organizations of all sizes that deal with large amounts of data. they are centralized repositories of all the data in organizations, including metadata such as