ost server-side applications require the ability to process tasks concurrently, which improves performance and increases utilization of hardware resources. In early versions of Java (1.4 or earlier), developers needed to implement concurrent applicationsincluding thread pool logicthemselves using low-level language constructs and the Java Thread API. The results were often poor. The nature of the Java Thread API often led unwitting programmers to develop code that introduced hard-to-debug programming errors.
In Java 5.0, Sun introduced the Java concurrency utilities (JSR-166) to address these issues and provide a standard set of APIs to create concurrent applications. This article explores some of the features provided by the Java concurrency package and demonstrates techniques for writing concurrent applications using these utilities.
Challenges of Concurrent Programming
Since its inception, Java has provided the Thread class and low-level language constructs such as synchronized
for developing platform-independent concurrent applications. However, building concurrent applications with these features has never been easy. Developers faced the following challenges:
- Incorrect programming can lead to deadlocks, where two or more threads waiting for each other are blocked forever.
- No mechanism is available for writing wait-free, lock-free algorithms in the Java language. Developers must use native code.
- Developers have to write their own complex thread pool logic, which can be tricky and prone to error.
Brief Overview of Java Concurrency Utilities
(Java concurrency utilities), which is part of Java 5.0, greatly simplifies the development of concurrent applications in Java by focusing on breadth and providing critical functionality that is useful across a wide range of concurrent programming styles.
Java concurrency utilities provides multiple features that developers can leverage for faster, more predictable development of concurrent applications. These features free developers from reinventing the wheel by writing custom code. Some of JSR-166's most notable features are:
- Standard interfaces and frameworks for defining custom thread-like sub systems
- A mechanism for standardizing invocation, scheduling, execution, and control of asynchronous tasks, according to a set of execution policies in the Executor framework
- A mechanism for thread coordination through classes such as semaphore, mutexe, barrier, latche, and exchangers
- Non-blocking FIFO queue implementation (the ConcurrentLinkedQueue class) for scalable, efficient thread-safe operations
- Blocking queue implementation classes to cover the most common usage contexts for the producer/consumer approach, messaging, parallel tasking, and related concurrent designs
- A framework for locking and waiting for conditions that is distinct from the built-in synchronization and monitors
- Ready-to-use classes for lock-free, thread-safe programming on single variables