This is the fifth in a series of articles looking at some of the JDK Enhancement Proposals (JEPS) hoping to make their way into Java 9. Last week we looked at HTML5 and Javadoc.
This week we’re looking at JEP 266: More Concurrency Updates, which is required as “…the continual evolution of uses of concurrency and parallelism in applications requires continual evolution in library support.” The JEP includes an interoperable publish-subscribe framework, enhancements to the
CompletableFuture API and other improvements such as Javadoc spec rewording.
An interoperable publish-subscribe framework
The Reactive Streams initiative provides a standard for asynchronous stream processing with non-blocking backpressure. It aims to solve the problem where elements are passed between threads or thread pools over time (the stream), and the receiving side gets varying amounts of data. If too much data comes in, the receiving side might become a bottleneck as it is still buffering the current data.
An example is events sent to an analytics engine to describe user interaction on a website. At peak times the number and size of events will increase, as more pages are viewed and links are clicked. If the receiver of the data doesn’t have the capacity to deal with incoming elements, future elements could be blocked until the existing ones are processed.
Before sending more data, we could check whether or not the receiver is overwhelmed. However this makes the communication synchronous, and thus the benefits of an asynchronous system, e.g. parallel computation, is lost. The Reactive Streams initiative provides a specification that relies on ‘backpressure’ to ensure that the receiver isn’t overwhelmed by incoming data. It does this using flow control and the publish-subscribe pattern. It allows the subscriber to be intelligent about its capacity rather than act as a dumb receiver.
The publish-subscribe pattern
The publish-subscribe pattern is a messaging pattern. Publishers ‘publish’ information to multiple subscribers. Subscribers define which information they want to receive with a subscription, and are unaware of the publishers. To meet the goal of the Reactive Streams initiative and achieve non-blocking backpressure, the subscriber controls the number of elements it will receive. It does this by requesting a certain number of elements at a time. This is a pull strategy as the subscriber is requesting messages rather than having messages pushed to it.
Java 9: Flow interfaces
The JEP provides interfaces that support the publish-subscribe Reactive Streams framework. This facilitates the creation of a
Flow.Publisher, which produces elements for a
Flow.Subscription links the
Flow.Publisher to a
Publication to the
Flow.Subscriber is asynchronous and is triggered by a request. The
Flow.Subscriber requests the elements from the
Flow.Subscription.request(long). It then processes the elements. It can request multiple elements, and a buffer size can be defined.
For more information and code examples, see the class
Enhancements to the
Future “represents the result of an asynchronous computation”. A
CompletableFuture is a Future that can be explicitly completed: it has a
CompletionStage that allows function and actions to be triggered when it has finished. It was introduced in Java 8 and is well described in Asynchronous Programming in Java 8: How to Use CompletableFuture.
The changes in Java 9 include:
- Support for delays and timeouts
- Better support for subclassing
It will also have a few new utility methods. These are to address common complaints and suggestions since the Java 8 introduction.
See A Journey into Reactive Streams, Building Microservices with Vert.x and Building a multiplayer game using Reactive Streams for more information on reactive streams.
See also the Reactive Streams JVM specification.