Introduction
Java 21 introduces several exciting features, with Project Loom taking center stage. After two preview versions with minimal changes, virtual threads are now officially part of Java 21, promising to revolutionize the performance of Java web applications.
Virtual Threads (Project Loom)
Virtual threads have become a definitive feature in Java 21 after being in preview for the past two versions. Virtual threads address a common bottleneck in web applications related to native threads. The limited number of available threads can hinder scalability when threads are blocked, waiting for API calls or database queries to complete. Project Loom’s virtual threads allow running millions of threads using only a few operating system threads, significantly improving scalability without requiring modifications to existing Java code.
Virtual threads bring significant advantages and reshape the programming landscape in Java by:
- Lightweight and Swift Creation: Virtual threads boast exceptional speed in creation, taking a mere 1 microsecond (1 µs) — a millionth of a second. In just 1 second, you could create 1 million virtual threads.
- Minimal Memory Requirements: Virtual threads demand significantly less memory — approximately 1,000 times less than a native thread (in flat call stacks). Comparatively, 1 kilobyte (KB) suffices for virtual threads, while each native thread consumes around 1 megabyte (MB).
- User-Space Locking and Rapid Context Switching: Locking operations occur in user space rather than in the operating system’s kernel, leading to exceptionally fast context switches. This design choice contributes to the efficiency of virtual threads.
- Simplified Code Transition: Transitioning from native threads to virtual threads requires minimal code changes. The adaptability of virtual threads allows for seamless integration without extensive modifications to existing codebases.
Sequenced Collections
Java 21 introduces three new interfaces for sequenced collections: SequencedCollection, SequencedSet, and SequencedMap. These interfaces represent collections with a defined order, simplifying the process of accessing elements sequentially or in reverse.
In earlier Java versions, accessing the last element of a list required more complex syntax:
var lastElement = list.get(list.size() - 1);
With the new sequenced collection interfaces, the process becomes more straightforward:
var lastElement = list.getLast();
Similar improvements apply to other collection types, such as obtaining the first element of a LinkedHashSet in Java 8.
In addition to getLast(), the SequencedCollection interface defines methods like addFirst(E), addLast(E), removeFirst(), removeLast(), and reversed(). The SequencedSet interface, derived from SequencedCollection, modifies the behavior of addFirst and addLast to move existing elements to the first or last position.
New Collection Methods
Java 21 extends the utility class Collections with static methods tailored for sequenced collections:
Collections.newSequencedSetFromMap(SequencedMap map);
Collections.unmodifiableSequencedCollection(SequencedCollection c);
Collections.unmodifiableSequencedMap(SequencedMap m);
Collections.unmodifiableSequencedSet(SequencedSet s);
Record Object Patterns
Records, transparent and immutable data carriers, gain a new feature in Java 21. Instead of traditional destructuring, access record components more concisely using object record patterns:
if (obj instanceof Point(int x, int y)) {
System.out.println(x + y);
}
Switch Statement with Record Patterns
Java 21 introduces the ability to use record patterns within switch statements, enabling automatic destructuring of values:
public void print(Object o) {
switch (o) {
case Point(int x, int y) -> System.out.printf("o is a position: %d/%d%n", x, y);
case String s -> System.out.printf("o is a string: %s%n", s);
default -> System.out.printf("o is something else: %s%n", o);
}
}
Other Stable Enhancements
- Emojis: The Character class includes methods to identify emojis.
- Math Clamp Method: The Math class now features a Clamp method for bounding a value within a specified range.
- Character Repeat Method: StringBuilder and StringBuffer gain repeat methods for appending a character sequence multiple times.
- String indexOf Overloads: The String class’s indexOf method adds overloads supporting a maxIndex parameter.
- List Shuffling: Collections.shuffle now supports shuffling lists in-place with a RandomGenerator.
Concurrency Structured API
Java 21 introduces a structured concurrency API to simplify concurrent programming. This API treats related task groups running in different threads as a single unit of work, streamlining error handling, improving reliability, and enhancing observability.
Scoped Values
Scoped values offer a modern way to share data within and between threads. These values are stored for a limited time, ensuring only the thread that wrote the value can read it. The ScopedValue.newInstance() method creates scoped values, and the ScopedValue.where() method links the value to an instance, maintaining its validity during the execution of a specified method.
Conclusion
Java 21 brings an array of stable and preview features, from the game-changing virtual threads to enhanced collection interfaces and utility methods. Developers can now take advantage of these innovations to write more efficient and concise Java code, ultimately improving the performance and maintainability of their applications. As we delve into the new features, it’s essential to stay informed and explore how these enhancements can benefit your specific use cases.