
So in a thread-per-request model, the throughput will be limited by the number of OS threads available, which depends on the number of physical cores/threads available on the hardware. With this, you can derive that throughput equals average concurrency divided by latency ( λ = L/W). Throughput of such systems can be explained using Little’s law, which states that in a stable system, the average concurrency (number of requests concurrently processed by the server), L, is equal to the throughput (average rate of requests), λ, times the latency (average duration of processing each request), W. For this, the preferred approach is the thread-per-request model, where a separate thread handles each request. One of the most common concurrency use cases is serving requests over the wire using a server. Let’s look at the two most common use cases for concurrency and the drawbacks of the current Java concurrency model in these cases. OS threads are at the core of Java’s concurrency model and have a very mature ecosystem around them, but they also come with some drawbacks and are expensive computationally. Project Loom aims to drastically reduce the effort of writing, maintaining, and observing high-throughput concurrent applications that make the best use of available hardware. I wrote more about Java concurrency in my Concurrency in modern programming languages: Java post. One has to resort to synchronizing threads to avoid issues like data races and thread blocking. This is primarily due to the shared state concurrency model used by default. Though the concurrency model in Java is powerful and flexible as a feature, it was not the easiest to use, and the developer experience hasn’t been great.

While things have continued to improve over multiple versions, there has been nothing groundbreaking in Java for the last three decades, apart from support for concurrency and multi-threading using OS threads. JDK 8 brought asynchronous programming support and more concurrency improvements. Java Development Kit (JDK) 1.1 had basic support for platform threads (or Operating System (OS) threads), and JDK 1.5 had more utilities and updates to improve concurrency and multi-threading. Java has had good multi-threading and concurrency capabilities from early on in its evolution and can effectively utilize multi-threaded and multi-core CPUs.
