join() method in java

In a multithreading environment, multiple threads can run concurrently. To control the execution of multiple threads java provides some method that exists in the Thread class and Object class. The join() method in java also exists in the Thread class. In this post, we will see how to use the join() method in java and how does thread join work?

Here is the table content of the article will we will cover this topic.
1. What is the join() method in java?
2. A real-life example of the join() method
3. Why we use join() method?
4. How does join() method work?
5. join() method
6. join(long millisecond) method
7. join(long millisecond, int nanoseconds) method

What is the join() method in java?

The join() method in java is used to pause the execution of a current thread unless the specified thread is dead. Suppose we have two threads thread1 and thread2. We want thread2 should be executed after thread1. We can achieve it by calling thread1.join() while thread2 is executing.  The join() method is used for adding sequencing between multiple threads e.g. one thread starts execution after the first thread finishes its execution.

thread1.join();

A real-life example of the join() method

Let’s say we want to print some pages by use of a printer (Which is thread1). But the printer is not in a ready state. Someone is repairing it(Which is thread2). So now thread1 can’t be complete until thread2 executes successfully. In this case, thread2 should be executed completely before thread1.

join() method in java

Why do we use join() method?

A program can have any number of threads. The thread scheduler takes responsibility to execute the threads. But a thread scheduler doesn’t give a guarantee to the order of execution of threads. If the thread scheduler has started the multiple threads in a sequential manner but the thread scheduler does not give end them in the specified order. Every time, we run the code may get a different result. 

So, the programmer has doubts, about why we use the join() method even though we can use the sleep() method to pause the execution.
The answer is simple sleep() method pauses the execution for a specific time period and we can’t predict the exact execution time of a thread. The join() method pauses a thread’s execution until the specified thread is dead. It is used for adding sequencing between multiple threads e.g. one thread starts execution after the first thread finishes its execution.

Let’s take an example of a program and see how does thread works. Here we have three threads thread1, thread2, and thread3. If we start the execution of all three threads in a sequence, the output may vary in different sequences.

public class MainThread 
{
   public static void main(String[] args) 
   {
      Thread thread1 = new Thread(new MyThread(), "thread1");
      Thread thread2 = new Thread(new MyThread(), "thread2");
      Thread thread3 = new Thread(new MyThread(), "thread3");
         
      thread1.start();
      thread2.start();        
      thread3.start();
   }
}
 
class MyThread implements Runnable
{
    @Override
    public void run() 
    {
    	Thread thread = Thread.currentThread();
    	for(int i = 1; i <= 3; i++)
    		System.out.println(thread.getName() + " running : "+ i);
        
        System.out.println("Thread ended: "+thread.getName());    
    }
}

Output: Thread started: thread2
Thread started: thread1
Thread started: thread3
Thread started: thread1
Thread started: thread2
Thread started: thread1
Thread started: thread3
Thread ended: thread1
Thread started: thread2
Thread ended: thread2
Thread started: thread3
Thread ended: thread3

We may get different outputs each time. But if we want the output in a sequenced manner, we need to use the join() method in java program.

public class MainThread 
{
   public static void main(String[] args) throws InterruptedException 
   {
      Thread thread1 = new Thread(new MyThread(), "thread1");
      Thread thread2 = new Thread(new MyThread(), "thread2");
      Thread thread3 = new Thread(new MyThread(), "thread3");
         
      // Start first thread immediately
      thread1.start();
         
      // Start second thread(thread2) after complete execution of first thread(thread1) 
      thread1.join();
      
      thread2.start();
         
      // Start second thread(thread2) after complete execution of first thread(thread1) 
      thread2.join();
      
      thread3.start();
   }
}
 
class MyThread implements Runnable
{
    @Override
    public void run() 
    {
    	Thread thread = Thread.currentThread();
    	for(int i = 1; i <= 3; i++)
    		System.out.println(thread.getName() + " running : "+ i);
        
        System.out.println("Thread ended: "+thread.getName());    
    }
}

Output: thread1 running : 1
thread1 running : 2
thread1 running : 3
Thread ended: thread1
thread2 running : 1
thread2 running : 2
thread2 running : 3
Thread ended: thread2
thread3 running : 1
thread3 running : 2
thread3 running : 3
Thread ended: thread3

In the above program, we can see all three threads are executing in a sequence. Here we are using the join() method that pauses the execution of the current thread and focuses on the joined thread. In the next section, we will see how does join() method work.

How does join() method work?

As we have discussed the join() method pauses the execution of the current. In the above example, we are writing the join() method in the main thread. So, it will pause the execution of the main thread.

join() method in java

There are three overloaded join functions:

1. join() method

This method doesn’t take any parameters. It will put the current thread on waiting until the thread on which it is called is completely executed. If a thread is interrupted, then it will throw InterruptedException. It doesn’t return anything. Its return type is void.

public final void join()
threadObject.join()
public class ExampleOfJoinMethod extends Thread
{  
   public void run()
   {  
	for(int i = 1; i <= 5; i++)
	{  
	  System.out.println(Thread.currentThread().getName() + " is running nd 
          value of i = "+i);  
	  try
	  {  
		Thread.sleep(500);  
	  } 
	  catch(Exception e)
          {
             System.out.println(e);
	  }  
      }  
    }  
    public static void main(String args[])
    {  
	ExampleOfJoinMethod thread1 = new ExampleOfJoinMethod();  
	thread1.setName("Thread1");
	ExampleOfJoinMethod thread2 = new ExampleOfJoinMethod();
	thread2.setName("Thread2");
		 
	thread1.start();  
	 
	try
	{  
	  thread1.join();  
	}
	catch(Exception e)
	{
	   System.out.println(e);
	}  
		  
	thread2.start();  
     }  
}

Output:
Thread1 is running and value of i = 1
Thread1 is running and value of i = 2
Thread1 is running and value of i = 3
Thread1 is running and value of i = 4
Thread1 is running and value of i = 5
Thread2 is running and value of i = 1
Thread2 is running and value of i = 2
Thread2 is running and value of i = 3
Thread2 is running and value of i = 4
Thread2 is running and value of i = 5

In the above example, we created two threads thread1 and thread2. Both threads are used to print the counting. But we want to execute thread2 after the completion of thread1. So, we called thread.join() method.

2. join(long millisecond) method

This method takes a parameter of a long type. It will put the current thread on wait until the thread on which it is called is dead or wait for a specified time. In this method programmer provides milliseconds it means to wait at most specified milliseconds for this thread to die. It will put the current thread on waiting for a specific time and the thread on which it is called is start the execution. After the timeout, it will again reschedule the threads. If a thread is interrupted, then it will throw InterruptedException.

Let’s say we have two threads thread1 and thread2. We want to execute thread2 before thread1 but for a specific time period. After the given timeout the control flow move out from thread1 and thread scheduler executes both threads. It doesn’t return anything. Its return type is void.

public final void join(long miliseconds)
threadObject.join(miliseconds)
public class ExampleOfJoinMethod extends Thread
{  
   public void run()
   {  
	for(int i = 1; i <= 5; i++)
	{  
	  System.out.println(Thread.currentThread().getName() + " is running nd 
          value of i = "+i);  
	  try
	  {  
		Thread.sleep(500);  
	  } 
	  catch(Exception e){System.out.println(e);
	}  
       }  
    }  
    public static void main(String args[])
    {  
	 ExampleOfJoinMethod thread1 = new ExampleOfJoinMethod();  
	 thread1.setName("Thread1");
	 ExampleOfJoinMethod thread2 = new ExampleOfJoinMethod();
	 thread2.setName("Thread2");
	 
	 thread1.start();  
	 
	 try
	 {  
	     thread1.join(1200);  
	 }
	 catch(Exception e)
	 {
	     System.out.println(e);
	 }  
	 thread2.start();  
       }  
}  

Output: Thread1 is running and value of i = 1
Thread1 is running and value of i = 2
Thread1 is running and value of i = 3
Thread2 is running and value of i = 1
Thread1 is running and value of i = 4
Thread2 is running and value of i = 2
Thread1 is running and value of i = 5
Thread2 is running and value of i = 3
Thread2 is running and value of i = 4
Thread2 is running and value of i = 5

3. join(long millisecond, int nanoseconds) method

This method takes two parameters one is the type of long and another is int. It will put the current thread on wait until the thread on which it is called is dead or wait for a specified time (milliseconds + nanosecond).In this method, the programmer provides milliseconds and nanoseconds which means waiting at the most specified time for this thread to die. It will put the current thread on waiting for a specific time and the thread on which it is called is start the execution. After the timeout, it will again reschedule the threads. If a thread is interrupted, then it will throw InterruptedException.

Let’s say we have two threads thread1 and thread2. We want to execute thread2 before thread1 but for a specific time period. After the given timeout the control flow move out from thread1 and thread scheduler executes both threads. It doesn’t return anything. Its return type is void.

public final void join(long milliseconds, int nanoseconds)
threadObject.join(milliseconds, nanoseconds)
public class ExampleOfJoinMethod extends Thread
{  
   public void run()
   {  
	for(int i = 1; i <= 5; i++)
	{  
	  System.out.println(Thread.currentThread().getName() + " is running nd 
          value of i = "+i);  
	  try
	  {  
		Thread.sleep(500);  
	  } 
	  catch(Exception e)
          {
             System.out.println(e);
	  }  
         }  
     }  
     public static void main(String args[])
     {  
	 ExampleOfJoinMethod thread1 = new ExampleOfJoinMethod();  
	 thread1.setName("Thread1");
	 ExampleOfJoinMethod thread2 = new ExampleOfJoinMethod();
	 thread2.setName("Thread2");
		 
	 thread1.start();  
	 
	 try
	 {  
	   thread1.join(1200, 10000);  
	 }
	 catch(Exception e)
	 {
	    System.out.println(e);
	 }  
		  
	 thread2.start();  
      }  
}  

Output: Thread1 is running and value of i = 1
Thread1 is running and value of i = 2
Thread1 is running and value of i = 3
Thread2 is running and value of i = 1
Thread1 is running and value of i = 4
Thread2 is running and value of i = 2
Thread1 is running and value of i = 5
Thread2 is running and value of i = 3
Thread2 is running and value of i = 4
Thread2 is running and value of i = 5

Leave a Comment