In Java, execution of the program starts from the main() method, from which all the remaining threads are created. These remaining threads are the child threads of the main thread. The execution of child threads takes place only after the main thread.

We can execute all threads independently, so that each thread has its own thread life cycle. As every thread has its own life cycle the individual thread can stop at any point of time (after its task has completed). But, what if the main thread stopped? This leads to the termination of all the child threads. But If we want to make the main thread to be wait till all the child threads has to be complete their work, that way the join() method is used to achieve this task.

Syntax:

final void join() throws InterruptedException
final void join(long mils) throws InterruptedException
final void join(long mils,int ns) throws InterruptedException

If a thread needs to wait until the completion of another thread, then we should apply the join() on top of that thread. The thread join() method is overloaded with 3 different flavours and every method throws InterruptedException. Hence whenever we use join(), we should handle the Exception or throw the Exception.

Thread join Flow Diagram:

Thread Join

Thread  join Example in Java

JoinDemo.java
class FirstThread extends Thread{
    String threadName;
    public FirstThread(String threadName){
        this.threadName = threadName;
        System.out.println("Created Thread " + threadName);
    }
    public void run(){
        try{
            for (int i = 0; i < 5; i++){
                System.out.println("From : " + threadName + " .." + i);
                sleep(1000);
            }
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}
public class JoinDemo{
    public static void main(String[] args){
        try{
            FirstThread firstThread = new FirstThread("First Thread");
            firstThread.start();
            firstThread.join();
            for (int i = 0; i < 5; i++){
                System.out.println("Main Thread : " + i);
            }
            System.out.println(" Main Thread : " + Thread.currentThread().isAlive());
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}

Output:

Created Thread First Thread
From : First Thread ..0
From : First Thread ..1
From : First Thread ..2
From : First Thread ..3
From : First Thread ..4
Main Thread : 0
Main Thread : 1
Main Thread : 2
Main Thread : 3
Main Thread : 4
Main Thread : true

In the above example, the main thread will wait for execution till the firstThread completes its task because we mentioned the firstThread.join();at line number 33. If we comment the line 33, then the execution of the two threads will happen simultaneously and we cannot expect the outcome of the program.

References:

Happy Learning 🙂