Java concurrency is a term that covers multithreading, concurrency, and parallelism on the Java platform, including Java concurrency tools, problems, and solutions. It covers the core concepts of multithreading, concurrency constructs, concurrency issues, costs, and benefits associated with multithreading in Java.

What is multithreading?

Multithreading means that there are multiple threads executing in an application, just like a single CPU. Thus, a multithreaded application is like having multiple cpus executing code in different parts of the application at the same time.

However, threads and CPUS are not exactly the same. Usually, multiple threads share the time slice of a single CPU and perform context switching between threads through the CPU. If there are multiple cpus, multithreading in an application may run on different cpus.

Why multithreading?

There are several reasons why you should use multithreading in your application. Some of the most common reasons for multithreading are:

  • Better use of a single CPU
  • Better utilization of multiple cpus or CPU cores
  • Fast response
  • More fair

Better use of a single CPU

One of the most common reasons is to be able to make better use of resources in your computer. For example, if one thread is waiting for a response to a request sent over the network, another thread can use the CPU to perform other operations simultaneously. In addition, if the computer has more than one CPU, or if the CPU has more than one execution core, multithreading also allows applications to take advantage of those additional CPU cores.

Better utilization of multiple cpus or CPU cores

If the computer contains more than one CPU or the CPU contains more than one execution core, the application uses more than one thread to use all cpus or CPU cores. A thread can only use one CPU at most, and as mentioned above, sometimes not even one CPU is fully utilized.

Fast response

For example, if you click a button in the GUI and send a request across the network, it matters which thread executes the request. If the thread being used is also updating the GUI, the user may experience a GUI “hang” while the GUI thread waits for the request response. Such requests can be executed by background threads, so GUI threads are free to respond to other user requests at the same time.

More fair

Fairly sharing of computer resources between multiple threads. For example, suppose a server receives requests from clients and only one thread executes them. If a client sends a request that takes a long time to process, all other client requests must wait until one request completes. By letting each client request be executed by its own thread, no single task can completely monopolize the CPU.

Multithreading and multitasking

In the past, a computer had only one CPU and could only execute one program at a time. Most minicomputers are not really powerful enough to execute multiple programs at the same time, so no attempt is made to do so.

multitasking

Then came multitasking, which meant that computers could execute multiple programs (i.e., tasks or processes) at the same time. But this is not “at the same time”. Programs share a single CPU. The operating system switches between running programs, and each program executes for a period of time before switching.

Programs can no longer assume that they have all available CPU time, all memory, or any other computer resources. A “good” program should free up all resources it no longer uses so that other programs can use them.

multithreading

Then came multithreading, which meant that more than one thread could execute in the same program. A thread of execution can be thought of as the CPU of an execution program. When there are multiple threads executing the same program, it is like executing multiple cpus within the same program.

Difficulties in multi-threading

Multithreading is a good way to improve the performance of certain types of programs. Threads execute in the same program and therefore read and write to the same memory at the same time. This can lead to errors that do not exist in a single-threaded program. Some of these errors might not be seen on a single CPU machine, because the two threads never really execute “simultaneously.” However, modern computers are equipped with multi-core cpus, or even multiple cpus, which means that different threads can be executed simultaneously by different cores or cpus.

If one thread is reading memory and another thread is writing to the memory address, what value did the first thread read last? Results are unpredictable and may change from time to time. Therefore, as a developer, it is important to know how to take the right precautions, how to control thread access to shared resources such as memory, files, databases, and so on.

Java multithreaded concurrency

Java has been multithreaded from the beginning. As a result, Java developers often face these problems.

This article focuses on multithreading in Java, but some of the problems that occur in multithreading are similar to those that occur in multitasking and distributed systems. Thus, references to multitasking and distributed systems may also appear in this area. Hence, the term “concurrency” rather than “multithreading”.

Concurrency model

The first Java concurrency model assumed that multiple threads executing in the same application would also share objects. This type of concurrency model is often referred to as the “shared state concurrency model.” Many concurrent language constructs and utilities are designed to support this concurrency model.

The shared-state concurrency model leads to many concurrency problems that are difficult to solve well. As a result, another model of concurrency called “no sharing” or “independent state” became popular. In the independent-state concurrency model, threads do not share any objects or data. This avoids many of the concurrent access problems of the shared state concurrency model.

New, asynchronous “state independent” platforms and toolkits such as Netty, Vert. X and Play/Akka and Qbit have appeared. New non-blocking concurrency algorithms have been released and new non-blocking tools such as LMax Disrupter have been added to our toolkit. The Fork and Join frameworks in Java 7 and the Collection Streams API in Java 8 introduce new functional programming parallelism.