Java Concurrency and Multithreading

Concurrency in Java refers to a group of terms revolving around multithreading, parallelism, and concurrent programming techniques. This includes not just programming theory and coding but concurrency tools as well. In this tutorial, we will look at what concurrency means in Java, the benefits, and the concepts and tools of multithreading.

What is Multithreading in Java?

The term multithreading in Java refers to having multiple threads - think of it loosely as a CPU or processor - executing separate sections of code in the same application at the same exact time. We say to look at it loosely as a thread is not technically a CPU or processor. In fact, perhaps a better way to think of multithreading is to discuss how normal programs work.

In a regular application, a CPU will run multiple threads of a program at separate times, switching back and forth between each thread as need be. Each thread, in this scenario, must wait its turn in line for resources to become available to run or execute. This is true whether you have one CPU or multiple ones.

Benefits of Multithreading in Java

There are many benefits of multithreading in Java, most of which have to do with the utilization of resources and application performance. These benefits apply whether you have a single processor or multiple ones.

For starters, if you rocked a single processor back in the day, your applications could better make use of your CPU resources. For instance, if one thread is in line waiting for a response from a network, another thread could, in turn, hop in and use the CPU for other purposes instead of waiting for it to open up. With the advent - and commonality - of multiple CPUs and cores, having multiple threads take advantage of the multiple cores and processing resources only makes sense.

Multithreading also benefits performance, as you might imagine. Instead of having a bottleneck of threads awaiting available resources (and thus longer wait times for the user), organizing your threads to better prioritize function within your application makes your software flow more seamlessly. Multithreading means that all of the threads within a process share the same resources, which include data, files, memory, and so forth. Thus, if part of the program is being held up, another part can run concurrently. A good example of this would be a game that needs to load images and sound. Instead of waiting for the images to load, the game could load sounds at the same time versus waiting until the images loaded first.

  • Other benefits of multithreading in Java include:
  • Decreased development time
  • Streamlined code
  • Tasks get performed simultaneously and concurrently, in parallel
  • Lower cost of maintenance
  • Maximized use of resources
  • Improved user experience and application responsiveness

Thread Lifecycle and States in Java

Threads in Java have a life cycle that consists of one of six states. At any given point in time, a thread can be in one - and only one - of these states, which include:

  • New
  • Runnable
  • Blocked Waiting
  • Time_Waiting
  • Terminated

New threads are threads that have been created but that have not yet been started. At this stage in the life cycle, the thread exists, but none of its code has been run or started to execute yet.

Runnable threads are threads that are ready to run or begin execution. Threads in this state can be ready to run or even running. For threads that are not yet running (but are ready to run), it means that they are simply waiting for resource allocation to occur.

Blocked threads are threads that are not eligible to run because they are waiting for a monitor lock. Blocked threads are either blocked or waiting. Blocked threads are trying to access a section of code that is locked by another thread; waiting threads are waiting on another thread based on a condition of some kind. Once the condition is met, the waiting thread is moved to runnable once more.

Time Waiting threads are threads that have called a method that has a time-out parameter invoked. It must wait until the time-out is over before it can continue running.

Terminated threads enter the terminated state when they have been fully executed. They can also become terminated when an error or exception occurs.