Java’s concurrency support has changed significantly over the last 20 years to mostly reflect the changes in hardware, software systems, and programming concepts. Going through the evolution of Java concurrency support can help in understanding the reason for the new additions and their roles. Initially, Java had threads and built-in monitor objects, which are supported by locks (via synchronized classes and methods), Runnable and Thread interfaces. The built-in monitor objects allow mutual exclusion and coordination among threads. The focus was on basic multi-threading and synchronisation primitives. They are efficient but low-level and very limited in capabilities. They are also difficult and error-prone to use, which can cause accidental complexity As per JDK 1.x release, there were only few classes present in this initial release. To be very specific, there classes/interfaces were: and some exception classes It also had few synchronized collections e.g. java.util.Hashtable. JDK 1.4, there were few JVM level changes to suspend/resume multiple threads with single call. But no major API changes were present. n 2004, Java 5 introduced new concurrency support: Java Executor framework, synchronizers, blocking queues, atomics, and concurrent collections. JDK 1.5 was first big release after JDK 1.x; and it had included multiple concurrency utilities. Executor, semaphore, mutex, barrier, latches, concurrent collections and blocking queues; all were included in this release itself. The biggest change in java multi-threading applications cloud happened in this release. Read full set of changes in this link: http://docs.oracle.com/javase/1.5.0/docs/guide/concurrency/overview.html It was a big step forward with better support compared to the earlier one. The idea of thread pools as a higher-level idea capturing the power of threads allowed developers to decouple task submission from task execution. It also enabled coarse-grained task parallelism (there was not a lot of computing power at that time), which is Also by Future and Callable interfaces, it provided higher-level and result-returning variants of Runnable and Thread. It is feature-rich and optimized but also difficult and error-prone as still uses low-levels of abstraction. Java 1.7 added foundational parallelism support. It provided data parallelism that runs the same tasks on different data elements. It added RecursiveTask to support fork-join approach of divide-and-conquer algorithms. Fork-join approach is powerful and scalable but tricky to program correctly Java 1.8 provided advanced level parallelism, which is support for streams and their parallel processing by building on the newly added support for lambdas. So, the focus was on functional programming for data parallelism and asynchronous programming. It added support for composing Futures via the CompletableFutures( implementation of Future) It provided an effective balance between productivity and performance Changes Java 9, provided explicit support for distributed asynchronous programming. It is basically the Flow API based on the publish-subscribe protocol, including back-pressure, and forms the basis for reactive programming. It is a set of interfaces for publish-subscribe model to standardize the concepts to maximize the interoperability of different implementations. As the new changes came in, the level of abstraction has been increased. It is good to learn the constructs on all levels. Learning low-level constructs will help in understanding the high-level constructs better and how they work underneath. As a rule of thumb, it is always good to use the simplest and most efficient option. So, it is better to start with using the most high-level option, which is Java 8’s concurrency/parallelism frameworks (i.e parallel streams and completable futures) or Java 9’s reactive programming) if it fits your needs. Consider using lower-level constructs only if needed, which should be rare at the application level. https://www.turgaykivrak.com/posts/2021-12-14-evolution-java-concurrency/Java’s Initial Concurrency Support
JDK 1.2 and JDK 1.3 had no noticeable changes related to multi-threading. (Correct me if I have missed anything).Java 5 Concurrency Changes
Java 7 Concurrency Changes
Java 8 Concurrency Changes
Java 9 Concurrency Changes
Which one to use?
来源