Java Concurrency Evolution

Since the early days of Java, Threads were available to support concurrent programming. Interestingly till Java 1.1, green threads (virtual threads) were supported by the JVM, but they were dropped in favor of native OS threads, however with Project Loom on the horizon (targeted for Java 16 or later?), virtual threads are on track to become mainstream again.

The goal of this article is to go through the main milestones for the evolution of thread/concurrency handling in Java. As the topic can easily fill a library full of books, the following aspects are out of scope (basically, the goal is to take a look at the happy path of Java concurrency):

Java Thread Synchronization and Concurrency Part 1

Introduction

Java thread synchronization and concurrency are the most discussed topics during various design phases of a complex application. There are many aspects of threads, synchronization techniques to achieve great concurrency in an application. The evolution of CPUs over the years (multi-core processors, registers, cache memory, and the main memory (RAM) has lead to some areas that usually developers tend to overlook — like thread context, context-switching, variable visibility, JVM memory model vs CPU memory model. 

In this series, we will discuss various aspects of the Java memory model, including how it impacts thread contexts, synchronization techniques in Java to achieve concurrency, race conditions, etc. In this article, we'll focus on the concepts of threads, synchronization techniques, and the memory models of both Java and our CPU.

Java Thread Synchronization and Concurrency Part 2

Introduction

This is the second part of my two-part series on thread synchronization. If you missed the first article, check it out. In the previous article, we covered concepts of threads, synchronization techniques, and memory model of both Java and CPU. In this article, we'll focus on concepts of concurrency, how to execute tasks in concurrent mode, and the various classes and services in Java that offer concurrency (thread-pool).

Multi-Threading Costs

Before getting into concurrency, we have to understand the costs associated with multi-threading. The costs include application design, CPU, memory, and context switching. Below are some of the considerations for concurrency:

Java SimpleDateFormat Is Not Simple

Formatting and parsing dates is a daily (painful) task. Every day, it gives us another headache.

A common way to format and parse dates in Java is using SimpleDateFormat. Here is a common class we can use.

Sharing Mutable Objects Using a Safe Accessor Service

On page 54 in his distinguished book "Java Concurrency In Practice," Brian Goetz describes how objects can be safely shared across threads. He lists four options:

  • The object is thread-confined, meaning updates to the object are performed by only one owning thread
  • The object is shared read-only, meaning this object only needs one-time publication
  • The object is inherently thread-safe, meaning it performs synchronization internally
  • The object is guarded by some lock

In this post, I will describe a variant that falls into the fourth category. The objects shared are not thread-confined, not read-only, and aren't synchronized internally. I am going to use a read-write lock to guard the object's state. As the presented technique is highly concurrent, it will not require synchronized blocks and gauruntees that no needless thread contention will slow down application performance. Without using synchronized, it is still garanteed that any change will be visible across all threads that share the object instances; this is achieved by applying certain rules to the shared objects' mutable state.

Tascalate Concurrent — Filling the Gaps in CompletableFuture API (Part 1)

The Tascalate Concurrent library provides an implementation of the CompletionStage interface and related classes. These are designed to support long-running blocking tasks (typically, I/O bound). This functionality augments the sole Java 8 built-in implementation, CompletableFuture, that primarily supports computational tasks. Also, the library helps with numerous asynchronous programming challenges like handling timeouts, retry/poll functionality, orchestrating results of multiple concurrent computations, and similar.

The library is shipped as a multi-release JAR and may be used both with Java 8 as a classpath library or with Java 9+ as a module.