Multithreading In Java With Examples

May 27, 2022
XBLOG multithreadingjavawithexamples



Introduction

We are living in the information age and this era demands that information is readily available to consumers through different gadgets and mediums. We as humans are impulsive and want things to happen quickly without much of waiting. We also like to multitask. Take an example of making breakfast. While boiling the eggs, we prepare tea and pan the toast. While having our breakfast we read the newspaper. Our attitude towards machines is also similar and specifically with computers and related electronic devices – we want them to perform the tasks quickly and give results sooner.

explore new Java roles

Due to this fact, hardware manufacturers of these devices are pumping more processing power into their architecture by expanding the number of CPU cores, memory, and disk space; so that information can be fetched and retained quickly. In support of these operating systems like Linux. iOS, Unix, Android, and Windows have in their arsenal, a concept known as multithreading. Taking advantage of this capability, high-level languages like Java have built-in support to perform multithreading tasks. In this post, we will explore the concept of multithreading in Java with examples. Let’s dive in.

Multithreading in Java

In Java, multithreading is a process of executing multiple threads concurrently for maximum utilization of the central processing unit commonly known as CPU. A thread is the smallest unit of execution of a program that runs sequentially. This concept is also known as Concurrency in Java. The benefit of using threads is that each thread runs in parallel hence multiple threads can run simultaneously in the same memory area allocated by a process. Switching between threads is also efficient and takes little time.

 

Following are some advantages of creating multithreaded applications:

  • Multithreading is a time saver as we can perform multiple operations in parallel.
  • Threads are independent and do not block the user to perform multiple operations at the same time.
  • An exception occurring in a single thread would not affect other threads.

Life Cycle of Thread

From a bird’s eye view, there are five states of a thread:

  1. New:-  This is also called a born thread. Thread remains in this state till the program starts the thread.
  2. Runnable:- In this state, the thread would be executing its task.
  3. Running:- The thread scheduler selects the thread and marks it as running.
  4. Non-Runnable (Blocked):- Thread is alive but is not eligible to run its task.
  5. Terminated:- A thread can end naturally after the execution of its task or ends due to an exception. After a thread is terminated it does not consume any CPU cycles.

Java Thread

There is a class available in Java that provides all the functionality related to threading. It has methods and overloaded constructors to perform operations on a thread. Let’s discuss a few of them here with examples.

public void Start():- It starts the execution of the thread and then calls the run() method on the Thread(declared with thrd in the example) object.

 

See Code Example Below:

public class Main extends Thread {
    public static void main(String[] args) {
      Main thrd = new Main();
      thrd.start();
  }
   public void run() {
       System.out.println("Hello! Thread is running...");
  }
}

Output: 
"Hello! Thread is running..."

public void run(): This thread is used to do an action for a thread. The run() method is instantiated if the thread was constructed using a separate Runnable object.

 

See Code Example Below:

public class RunExample implements Runnable 
{ 
   public void run() 
   { 
       System.out.println("Hello! Thread is running..."); 
} 
  public static void main(String args[]) 
  { 
   RunExample r = new RunExample(); 
    Thread thrd =new Thread(r1); 
     thrd.start(); 
  } 
}

Output: 

"Hello! Thread is running..."

Concurrency Issues

Since threads run at the same time along with the rest of the code block within the program, there is no way to know in which order the code will run. When the threads and main program are reading and writing the same variables, the values become unpredictable. This is known as concurrency issues.

 

Here is an example:

public class ConcurrencyExample extends Thread {
    public static int amount = 0;

   public static void main(String[] args) {
    ConcurrencyExample thrd = new ConcurrencyExample();
    thrd.start();
    System.out.println(amount);
    amount++;
    System.out.println(amount);
}

   public void run() {
   amount++;
   }
}

Here, the value of the amount variable is unpredictable. To avoid this kind of issue, try to share a few attributes between threads as possible. However, If attributes need to be shared due to programming logic, then use the isAlive() method of the thread to check whether the thread has finished running before using any attributes that the thread can change. Let’s use isAlive() in an example:

public class IsAliveExample extends Thread {
  public static int amount = 0;

  public static void main(String[] args) {
    IsAliveExample thread = new IsAliveExample();
    thrd.start();
    // Wait for the thread to finish
    while(thr.isAlive()) {
    System.out.println("Waiting for thread to finish...");
  }
  // Update amount and print its value
  System.out.println("Amount: " + amount);
  amount++;
  System.out.println("Amount: " + amount);
  }
  public void run() {
    amount++;
  }

}
Output: 
"Waiting for thread to finish..."
"Waiting for thread to finish..."
"Waiting for thread to finish..."
"Amount: 1"
"Amount: 2"

In the above example, the count of output “Waiting for thread to finish…” can vary depending upon your CPU usage.

Inter-thread Communication

In Java, threads can communicate with each other as well and there are three methods which are provided by the language which are:

wait():- Informs the calling thread to give up the monitor and go to sleep until some other thread enters the same monitor and calls notify().

notify():-  Wakes up the first thread that called wait() on the same object.

notifyAll():- Wakes up all the threads that called wait() on the same object. The highest priority thread will run first.

All the above methods can only be called from a synchronized method and to synchronize the threads Java has the concept of a monitor. A monitor can be thought of as a box that can hold only one thread. Once a thread enters the monitor, all the other threads have to wait until that thread exits the monitor.

Conclusion

For any large Java project multithreading is a must-do task. Without introducing multithreading to the application development one can face severe bottlenecks in terms of memory and CPU usage. Utilizing the concepts presented in this post will greatly improve the overall experience of your application, thus making your customers happy.

Also Read: Java Expressions with Examples

new Java jobs



author

waqas

I am a senior technical project manager in a reputable US based software development company. I have been developing and managing innovative solutions for multinational companies, deployed software and systems. I am responsible for full life cycle development of next-generation software, from initial requirement gathering to design, coding, testing, documentation and implementation. Being in technology I love to write about it.


Candidate signup

Create a free profile and find your next great opportunity.

JOIN NOW

Employer signup

Sign up and find a perfect match for your team.

HIRE NOW

How it works

Xperti vets skilled professionals with its unique talent-matching process.

LET’S EXPLORE

Join our community

Connect and engage with technology enthusiasts.

CONNECT WITH US