Home / Java

Multithreading in Java

Rating: 4.0Blog-star
Views: 1977
by Ruchitha Geebu
Last modified: March 2nd 2021

Multithreading is the basic concept of Object-Oriented Programming which revolves around real-life entities.


What is Multithreading?

Multithreading in Java is a process where multiple threads/tasks executed simultaneously. A thread is a lightweight, smallest sub-process. Threads are assigned a shared memory area. They don’t have a separate memory area. So, this saves memory, and context switching between threads will be faster than the process. This concept is mostly implemented in games and animation.

 

Want to become a Java Developer?  Visit here to learn Core Java Online Training


lifecycle of a Thread

Below are different stages of a thread lifecycle:

img

  • New: This is the first stage of any newborn thread. Until the program starts the thread, the thread remains in the new state.
  • Runnable: Once it is invoked, the thread will be in a runnable state until it is picked up by the scheduler to run.
  • Running: Once the thread scheduler selects the thread, its state will be changed from runnable to running.
  • Waiting: The thread will be in waiting for the state when it is alive but not eligible for running.
  • Dead: Once the thread is existed or terminated, its state will change to dead.

Creating a Thread in Java

Before creating a thread in Java, let us first go through some important methods of the thread which we are going to use in the following examples.

Method Name Meaning
start() This method is responsible for starting the execution of the thread.
Sleep(int milliseconds) This method is responsible for making thread sleep. While sleeping, the thread’s execution will stop and resume after the millisecond's pause we have given. This is helpful for the synchronization of threads.
getName() Returns the thread name
setPriority(int newpriority) This method is responsible for setting the priority of a thread.
run () It is a thread’s entry point.
getPriority() Returns a thread’s priority
isAlive() Returns true if thread is alive else false

Java has below 2 methods to create and use a thread.

Extend Thread class

Here, we need to create a class that is extending the Thread class. The class which we have created must override a run() method, which is the entry point for any new thread. Now we can access this class by creating an object of it. Through this object, we need to initiate start() method to initiate the execution of the thread. Below is an example of same.

class ThreadDemo extends Thread 
{ 
    public void run() 
    { 
        try
        { 
           System.out.println (Thread.currentThread().getName() + 
                  " is running"); 
  
        } 
        catch (Exception e) 
        { 
           System.out.println ("Into Thread Exception"); 
        } 
    } 
} 
  
 
public class Main 
{ 
    public static void main(String[] args) 
    { 
        int n = 5; 
        for (int i=0; i

Output:

Thread-0 Alive
Thread-0 is running
Thread-1 Alive
Thread-1 is running
Thread-2 Alive
Thread-2 is running
Thread-3 Alive
Thread-3 is running
Thread-4 Alive
Thread-4 is running

Implement Runnable interface

Here, we need to create a class that implements the Runnable interface. Runnable interface needs run() method to be implemented in the class which implements Runnable interface. run() method will have code that creates a new thread. Once the class is prepared, we can instantiate that class and use the object of that class to start the execution of the thread. Below is an example of the same.

class ThreadDemo implements Runnable
{
   Thread th ;
   ThreadDemo()
   { 
      th = new Thread(this, "Test Thread");
      System.out.println("Thread Created" + th);
      th.start();
   }
   public void run()
   {
      try
      {
        for (int i=0 ;i<5;i++)
        {
          System.out.println("Thread " + i);
          Thread.sleep(1500);
        }
     }
     catch(InterruptedException e)
     {
        System.out.println("Thread interrupted");
     }
     System.out.println("Exiting the thread" );
   }
}
public class Main
{
    public static void main(String args[])
    {
       new ThreadDemo();
    }
}

Output:

Thread CreatedThread[Test Thread,5,main]
Thread 0
Thread 1
Thread 2
Thread 3
Thread 4
Exiting the thread

Check Out Core Java Tutorials

Synchronization

Synchronization is the process to assure that the resources are only used by one thread at a time. If one resource is used by multiple threads, then that can create a deadlock situation. To avoid that, we need to implement synchronization in our code.

Java has provided the synchronized approach while writing the code to assure the behavior. So, when one thread enters the synchronized block, no other thread can enter the same method. All other threads need to wait until the first thread finishes the execution. Once it is finished, other threads can start their execution.

Let us see the below example where multiple threads try to use the same method.

class Demo {
    void call(String msg) {
        System.out.print("[" + msg);
        try {
                Thread.sleep(1000);
        } catch(InterruptedException e) {
                System.out.println("Interrupted");
        }
        System.out.println("]");
    }
}
 
class Test implements Runnable {
    String msg;
    Demo target;
    Thread t;
    public Test(Demo targ, String s) {
        target = targ;
        msg = s;
        t = new Thread(this);
        t.start();
    }
 
    public void run() {
        target.call(msg);
    }   
}
public class SynchronizeDemo {
    public static void main(String args[]) {
        Demo target = new Demo();
        Test ob1 = new Test(target, "Learn");
        Test ob2 = new Test(target, "Synchronized");
        Test ob3 = new Test(target, "Java");
        // wait for threads to end
        try {
            ob1.t.join();
            ob2.t.join();
            ob3.t.join();
        } catch(InterruptedException e) {
                System.out.println("Interrupted");
        }
    }
}

Output:

[Synchronized[Java[Learn]
]
]

Here we can see, call() method has switched execution to another thread and that is why we are getting mixed string as output. This is termed as race condition. Here 3 threads are racing with each other to complete their execution. Here output is not predictable as we are not aware and when the context switch will happen. Due to this, the program can run correctly at one time but wrong at next. 

To avoid this situation, we must restrict the access to the call the method by using the keyword synchronize in the method call like shown below:

synchronized void call(String msg)

If we modify the above program and add synchronize keyword to the call() method then the output will be like below:

[Learn]
[Java]
[Synchronized]

 

About Author

author
NameRuchitha Geebu
Author Bio

I am Ruchitha, working as a content writer for MindMajix technologies. My writings focus on the latest technical software, tutorials, and innovations. I am also into research about AI and Neuromarketing. I am a media post-graduate from BCU – Birmingham, UK. Before, my writings focused on business articles on digital marketing and social media. You can connect with me on LinkedIn.