9
Asynchronous

WHAT’S IN THIS CHAPTER?            

  • Introduction to asynchronous programming
  • What is asynchronous programming
  • Asynchronous programming using threads
  • Using asynchronous programming in beans
  • Asynchronous programming in servlets
  • When and where to best use asynchronous techniques

WROX.COM CODE DOWNLOADS FOR THIS CHAPTER

The wrox.com code download for this chapter is found at www.wrox.com/go/projavaeedesignpatterns on the Download Code tab. The code is in the Chapter 9 download and individually named according to the names throughout the chapter.

Although asynchronous programming is not always listed as a design pattern, it has been a popular and important programming model for the past decade. The asynchronous programming model relies on multithreading and executing the given functionality in a separate thread. Not only do multithreaded environments and programming languages take advantage of asynchronous programming techniques, but single-threaded platforms, such as the popular server-side JavaScript platform NodeJS, make good use of asynchronous programming principles.

Java was designed to support multiple threads from its start. However, it failed to provide a simple approach to making asynchronous calls. The Future<T> interface, which was introduced in Java 5, was Java’s first attempt at implementing asynchronous programming, but it was cumbersome and tricky to use. Subsequent versions of Java introduced the @Asynchronous annotation. The asynchronous servlet provided a much better set of tools to aid in asynchronous programming.

WHAT IS ASYNCHRONOUS PROGRAMMING?

The asynchronous programming pattern is a special and well-integrated case of multiple threads. Due to the nature of threads, multithreading models tend to need notification systems and depend on boilerplate code to initiate threads.

Asynchronous calls are used even in single-threaded environments like Node.JS. Almost all user interface (UI) frameworks use asynchronous execution to keep UI active and responsive. The first “A” of AJAX,1 which powered the Web 2.0 movement, stands for asynchronous.

However, asynchronous programming can be useful in places other than user interfaces, typically on the sever side. Neither J2SE nor J2EE offered a built-in easy implementation for asynchronous programming. With Java 5, the Concurrency Framework, based on JSR166, was released. JSR166 included many utilities that made asynchronous programming possible, easier, and better controlled. The Future<V> interface also provided a way to help developers to implement asynchronous method execution.

Meanwhile, Spring offered asynchronous method calls, which are enabled with annotations. Java EE did not include such a convenient solution until version 6.0. The @Asynchronous annotation was introduced with Java EE 6 and offered an easy way to implement asynchronous method execution.

Asynchronous Pattern

Asynchronous programming is not listed as a design pattern in either the GoF2 book or in the Head First Design Patterns3 book. If it was, its description might be “Provides a way to invoke a method without blocking the invoker.”

The nature of method execution is to block the caller until the called method finishes its execution. This behavior is straightforward and expected but may not be desired in all cases. Almost all UI frameworks and web platforms rely on nonblocking requests.

The asynchronous pattern relies on the fire and forget approach where an operation is done in parallel or in a way not blocking the executor thread, and the result is checked when it is ready. Usually the asynchronous approach makes use of parallel execution. It may not be accurately reflected with a class diagram but may be better shown with a flow diagram. Figure 9.1 demonstrates several asynchronous execution flows.

images

Figure 9.1 Asynchronous flow diagram

IMPLEMENTING ASYNCHRONOUS PATTERN 
IN PLAIN CODE

Java has supported threads that you can easily use for asynchronous code execution from its initial design:

public class AsyncRunnable implements Runnable {

    public void run() {
        System.out.println("Running!");
    }
}

To execute the Runnable class, initialize it in a thread and invoke the run method by calling the start() method on the newly created thread:

(new Thread(new AsyncRunnable())).start();

Although the preceding example is the preferred way to start a thread process, another approach is to extend the thread class and override the run() method:

public class AsyncThread extends Thread {

    public void run() {
        System.out.println("Running!");
    }

}

To execute the class, instantiate it and then call the start() method:

(new HelloThread()).start();

Two essential operations are commonly used when dealing with threads: sleep() and join(). Both operations throw an InterruptedException.

The sleep() method lets the thread sleep for a specified period, given in milliseconds. The following code snippet puts the current thread into the sleep state for one second:

Thread.sleep(1000);

The join() method makes one thread wait for another thread’s execution to finish. Consider a thread, t1, that needs a resource from another thread, t2. To make t1 wait for t2 to finish, join t1 to t2, as shown in the following code snippet:

t2.join();

One of the most well-known and widely used approaches to programming asynchronously in Java is using the Future<V> interface. This interface enables the use of a proxy object, which offers a reference for the future object. Because the concurrency framework does not offer annotation-based support for asynchronous execution, the Future interface is mostly coupled with an ExecutorService, which is part of the concurrency framework.

The following example uses an executor service to complete a task while it returns a reference to the Future interface with the appropriate generic type:

ExecutorService executor = Executors.newSingleThreadExecutor();

Future<String> reference = executor.submit(
    new Callable<String>() {
        public String call() {
            return "Hello!!";
        }
    }
);
//..
if (reference.isDone())
    System.out.println(reference.get());

The FutureTask class is an implementation of the Future<T> interface, which implements the runnable interface and can be executed directly:

FutureTask<String> reference = new FutureTask<String>(
    new Callable<String>() {
        public String call() {
            return "Hello!!";
        }
    }
);

executor.execute(reference);

You can cancel this execution by calling the cancel(boolean mayInterruptIfRunning) method. If the mayInterruptIfRunning parameter is set to true, calls to the method SessionContext
.wasCancelled() return true. Otherwise, a call to the SessionContext.wasCancelled() method returns false. To check the status of cancelation, you can use the isCancelled() method, which returns true if a cancelation is successful.

The concurrency framework JSR-133 offers great tools for threads and concurrent programming, such as BlockingQueues. These topics are beyond the scope of this chapter. See the book Java Concurrency in Practice4 for further reading. The Fork/Join Framework, which was introduced in Java 7, also offers a huge change in favor of asynchronous and parallel programming in Java.

ASYNCHRONOUS PROGRAMMING IN JAVA EE

Because J2EE failed to offer built-in support for the asynchronous programming paradigms (except for Timer), third-party frameworks, such as Spring and Quartz, stepped in to fill this gap. This deficit was corrected in Java EE 5; it was the first Java version to support the asynchronous programming pattern out of the box.

Asynchronous Beans

Java EE supports asynchronous programming in several ways. The simplest way to implement the asynchronous pattern in Java EE is, not surprisingly, via the application of an annotation. Annotating a method with @Asynchronous is enough to advise the Java EE container to asynchronously execute the invoked method in a separate thread. To see the asynchronous annotation in action, go back to the singleton logging bean example in Chapter 4, “Singleton Pattern” and add the asynchronous annotation to change its default behavior. Listing 9-1 shows an example of an asynchronous bean.

The logAsync() method, unlike its logInfo() counterpart, is executed asynchronously. To observe asynchronous behavior, add Thread.sleep() calls:

public void logInfo(String msg) {
   logger.info("Entering sync log");

  try {
      Thread.sleep(1000);
  } catch (InterruptedException e) {}

  logger.info(msg);
}


@Asynchronous
public void logAsync(String msg {
  logger.info("Entering async log");

  try {
     Thread.sleep(13000);
  } catch (InterruptedException e) {}

  logger.info(msg);
}

Finally, create a new bean to call both functions in order, as shown in Listing 9-2.

A typical console output would be as follows:

> call async

> Entering async log

> call sync

> Entering sync log

> Log Sync

> finished

> Log Async

After you execute the testLoggers() method, call the logAsync() and logSync() methods. Both methods let their execution thread sleep for the given length of time. As can be seen from the console output, the async() method was called and went into a long sleep but did not lock the execution of the sync() method. The sync() method sleeps for a while but returns control to the caller method and prints finished. Finally, the async() method wakes up and finishes logging by printing Log Async to the console.

This example clearly shows that the asynchronous call does not stop the caller thread, nor does it stop the sync() method. However, when the sync() method goes into the sleep state, the caller method waits until the sleep ends. The @Asynchronous annotation is an easy way to implement asynchronous behavior and can be added to almost any method at any time during and after development.

Asynchronous Servlets

So far, you have seen that you can convert any method of a bean to an asynchronous method. Now you’ll look at how to make a servlet act asynchronously. Without asynchronous support in servlets, it is hard to respond to the asynchronous web challenge.

The Servlet 3.0 specification (JSR 315) made huge improvements to the Java web application programming interfaces (APIs). With JSR 315, the servlet specification was updated (after a long wait) to support an asynchronous execution model, easy configuration, pluggability, and other minor enhancements.

Asynchronous servlets rely on a basic improvement in Hypertext Transfer Protocol (HTTP) 1.1, which enabled persistent connections. In HTTP 1.0, each connection is used to send and receive only a single request and response couple; however, HTTP 1.1 allowed web applications to keep the connection alive and to send multiple requests. On a standard implementation, the Java back end would need a separate thread constantly attached to the HTTP connection. However, Java nonblocking I/O (NIO) APIs recycle threads between active requests, thanks to the new NIO capability. Today all web servers compatible with the Servlet 3.0 specification have built-in support for Java NIO. Why do you need such behavior from servlets? The nature of back-end systems involves lengthy operations such as connecting to other servers, performing complex calculations, and making transactional database operations. However, the nature of web pages requires quite the opposite. Web users expect fast response times and a functional UI even if back-end operations are completed. AJAX addressed this issue for the browser and started the Web 2.0 revolution.

Servlet 3.0 introduced the startAsync() method, which enabled asynchronous operations. Listing 9-3 shows an example.

This servlet prints Results: and later prints retrieved data from the database, which is a simple string in this scenario. You need to initialize a separate thread. AsyncListener’s onComplete method is executed only when the execution completes. Several other life cycle methods exist in the AsyncListener:

  • onStartAsync—executes when the asynchronous context starts
  • onTimeOut—executes only if a timeout occurs
  • onError—executes only if an error is received

The Servlet 3.1 specification provided an easier way to implement asynchronous servlets by using managed thread pools and the executor service. The example in Listing 9-4 uses a ManagedThreadFactory to create a new thread.

This example creates a new thread that hosts the time-consuming process and finally calls a complete function from asyncContext. ManagedThreadFactory serves as an available thread from the pool that you need to start explicitly.

Another approach is to submit the asynchronous runnable to ManagedExecutorService instead of creating and starting the thread in the servlet. Delegating threading issues to ExecutorService provides cleaner code, as you’ll see in Listing 9-5.

Although it’s just one line less than the previous listing, Listing 9-5 delegates the creation and starting of the thread to the ExecutorService and only deals with servlet-specific code.

Asynchronous servlets are easier to understand and code and have an immediate effect on runtime behavior because it directly switches to the asynchronous execution model. Asynchronous servlets provide a clean implementation without a lot of boilerplate code.

WHERE AND WHEN TO USE ASYNCHRONOUS 
PROGRAMMING

You can use the asynchronous pattern almost anywhere where it is required to return a response before all the execution is complete. This approach can vary from executing the less important functions of the application asynchronously, such as logging or keeping the user informed about a time-consuming operation. Asynchronous programming makes the critical execution path shorter while delegating subtasks to other threads. The result is better response times.

Asynchronous annotation is a simple way to implement asynchronous methods or convert existing ones. Each method marked with the asynchronous annotation runs in a separate thread without locking the current thread’s execution. This behavior is a perfect match for conditions that do not affect the main execution cycle but need to be performed on the back end. Examples include logging and maintenance resources.

You can use asynchronous servlets in almost all modern web apps. Asynchronous servlets provide nonblocking asynchronous behavior without a special need for AJAX. Asynchronous servlets can help when a server-based push operation is needed, such as updating information or delivering a message.

Because each asynchronous execution requires a new thread, the Java Virtual Machine (JVM) needs to perform more context switches as more asynchronous methods are implemented. A large number of context switches cause thread starvation and result in poorer performance than a synchronous implementation.

Imagine that you are reading one book. Between reads, you must remember the story, the characters, and the last page you’ve read. If you’re reading two books at the same time, you may finish the second shorter book without needing to finish the longer one you started. The time spent changing context from one book to the other is acceptable.

Reading six books in parallel would be challenging. It may require so many context changes that you may not be able to finish any of the books in the expected time and end up changing from one book to the other without making much progress in any of them.

Asynchronous programming radically modifies the execution order and therefore debugging. Because debugging relies on suspending the execution and then stepping line by line through it, it is more difficult to understand the execution behavior and to mimic what is really happening. The JVM determines the execution order of threads at run time. It is almost impossible to simulate the same behavior because of very different available resources on test and development environments. If you don’t need it, asynchronous execution adds undesired complexity.

Threading and asynchronous execution can be a great tool only if used properly without starving resources. It is a good idea to run nonblocking parts asynchronously, but not on every method.

SUMMARY

In the age of multicores and web 2.0, asynchronous programming uses computing resources, delegates nonblocking tasks, and results in faster and more responsive user interfaces. Even if your application does not implement the asynchronous pattern, most application servers and JVMs use asynchronous execution internally via thread pools for many operations. Using those available threads and resources greatly affects your application’s efficiency and responsiveness.

Threading has been a first-class citizen from the early days of Java, but using threads to run asynchronous tasks was complicated and wasn’t always safe in server-managed containers. With the release of the Concurrency Framework, Java unleashed a huge set of tools into the hands of Java developers.

Java EE followed this trend by providing an easy-to-use and implement annotation-based asynchronous programming model. Adding the @Asynchronous annotation tells the container to execute the function asynchronously.

The servlet API introduced important changes in release 3.0 and further improvements in release 3.1. The new servlet API uses the new nonblocking Java I/O to support asynchronous web programming in an efficient way. Although previous approaches needed a request/response couple to be bound to a thread, the new model can use or release threads using the internal thread pool that the container provides.

Today Java EE offers all the needed tools to run asynchronous code without the need for a third-party framework such as Spring or Quartz. This makes the asynchronous pattern a great tool to implement if you want to execute nonblocking code asynchronously with almost no boilerplate code.

  EXERCISES  

  1. Create an implementation of a session bean that has an asynchronous method.

  2. Develop simple functionality that uses asynchronous methodology to persist application log data to a database.

  3. Use the asynchronous feature of Servlet 3.0 to design an asynchronous web service.

NOTES

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.193.124