Saturday, March 14, 2026

isAlive() And join() Methods in Java Multi-Threading

In this tutorial we'll see what are isAlive() and join() methods in Java, which give you precise control over thread lifecycle management, ensuring smoother synchronization and more predictable program behavior.

When working with multiple threads in Java, developers typically create threads and invoke the start() method to begin execution. Once started, the Java Virtual Machine (JVM) automatically calls the run() method when system resources and CPU are available. The thread then executes its task and eventually transitions to the terminated state.

But what if you need to trigger further processing only after a specific thread has finished? How can you reliably check whether a thread is still running or has ended?

This is where the isAlive() and join() methods in Java come into play. These two powerful methods in Java’s multithreading API allow you to:

  • isAlive()– Quickly verify if a thread is still active.
  • join()– Pause the execution of the current thread until the target thread completes.

isAlive() method in Java

isAlive() method is the member of the Thread class and its general form is–

public final boolean isAlive()

The isAlive() method in Java is used to check whether a thread is currently active. A thread is considered alive if it has been started using the start() method and has not yet reached the terminated state. When you call isAlive() on a thread object, it returns:

  • true- if the thread is still running or in a runnable state.
  • false- if the thread has finished execution or has not been started

This makes the isAlive() method a simple yet powerful way to monitor thread lifecycle and ensure that your program executes tasks in the correct order. By combining isAlive() with other multithreading techniques, developers can build more predictable and synchronized applications.

join() method in Java

Join() method is used when you want to wait for the thread to finish. Its general form is–

public final void join() throws InterruptedException

This method waits until the thread on which it is called terminates. There are three overloaded join functions.

  • public final void join()- Waits indefinitely for this thread to die.
  • public final void join(long millis)-Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever.
  • public final void join(long millis, int nanos)- Waits at most millis milliseconds plus nanos nanoseconds for this thread to die.

Java Example code using join and isAlive()

Imagine a situation where your application spawns multiple threads to perform heavy computations. You want the user to see the message "Processing is done" only after all threads have completed their tasks.

In such cases, the join() method in Java is the ideal solution. By calling join() on a thread, the current thread (often the main thread) pauses execution until the specified thread finishes. This ensures that your program doesn’t move forward prematurely and that the final message is displayed only after all computations are complete

Now first let’s try to do something like this without using join() method.

class MyRunnableClass implements Runnable{
  @Override
  public void run() {
    for(int i = 0; i < 5 ; i++){
      System.out.println(Thread.currentThread().getName() + " i - " + i);
      try {
        Thread.sleep(100);
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  }    
}
public class JoinExample {
  public static void main(String[] args) {
    Thread t1 = new Thread(new MyRunnableClass(), "t1");
    Thread t2 = new Thread(new MyRunnableClass(), "t2");
    Thread t3 = new Thread(new MyRunnableClass(), "t3");
     
    t1.start();
    t2.start();
    t3.start();
        
    System.out.println("t1 Alive - " + t1.isAlive());
    System.out.println("t2 Alive - " + t2.isAlive());
    System.out.println("t3 Alive - " + t3.isAlive());
        
    /*try {
        t1.join();        
        t2.join();
        t3.join();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }        
    System.out.println("t1 Alive - " + t1.isAlive());
    System.out.println("t2 Alive - " + t2.isAlive());
    System.out.println("t3 Alive - " + t3.isAlive());*/        
    System.out.println("Processing finished");
  }
}

Output

t1 Alive - true
t2 Alive - true
t3 Alive - true
Processing finished
t3 i - 0
t1 i - 0
t2 i - 0
t3 i - 1
t1 i - 1
t2 i - 1
t2 i - 2
t1 i - 2
t3 i - 2
t3 i - 3
t1 i - 3
t2 i - 3
t3 i - 4
t1 i - 4
t2 i – 4

Here it can be seen that the message is displayed much before the actual processing has finished.

Now let’s uncomment the code related to join and run the program again.

class MyRunnableClass implements Runnable{
  @Override
  public void run() {
    for(int i = 0; i < 5 ; i++){
      System.out.println(Thread.currentThread().getName() + " i - " + i);
      try {
        Thread.sleep(100);
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  }
}
public class JoinExample {
  public static void main(String[] args) {
    Thread t1 = new Thread(new MyRunnableClass(), "t1");
    Thread t2 = new Thread(new MyRunnableClass(), "t2");
    Thread t3 = new Thread(new MyRunnableClass(), "t3");
     
    t1.start();
    t2.start();
    t3.start();
    
    System.out.println("t1 Alive - " + t1.isAlive());
    System.out.println("t2 Alive - " + t2.isAlive());
    System.out.println("t3 Alive - " + t3.isAlive());
        
    try {
      t1.join();        
      t2.join();
      t3.join();
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
        
    System.out.println("t1 Alive - " + t1.isAlive());
    System.out.println("t2 Alive - " + t2.isAlive());
    System.out.println("t3 Alive - " + t3.isAlive());
    
    System.out.println("Processing finished");
  }
}

Output

t1 Alive - true
t2 Alive - true
t3 Alive - true
t2 i - 0
t3 i - 0
t1 i - 0
t1 i - 1
t2 i - 1
t3 i - 1
t3 i - 2
t1 i - 2
t2 i - 2
t1 i - 3
t2 i - 3
t3 i - 3
t2 i - 4
t3 i - 4
t1 i - 4
t1 Alive - false
t2 Alive - false
t3 Alive - false
Processing finished

Now see how message is displayed only when the processing is actually finished and all the threads are terminated. The second print statements using isAlive() method confirms that the threads are not running any more.

That's all for this topic isAlive() And join() Methods in Java Multi-Threading. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Difference Between sleep And wait in Java Multi-Threading
  2. Creating a Thread in Java
  3. Synchronization in Java - Synchronized Method And Block
  4. Race Condition in Java Multi-Threading
  5. Java Multithreading Interview Questions And Answers

You may also like-

  1. Creating Custom Exception Class in Java
  2. Interface Static Methods in Java
  3. Fail-Fast Vs Fail-Safe Iterator in Java
  4. Java Lambda Expression And Variable Scope
  5. Find All Permutations of a Given String Java Program
  6. Abstraction in Java
  7. Java ReentrantReadWriteLock With Examples
  8. Bean Scopes in Spring With Examples

1 comment:

  1. Your blog has good material for Java, multithreading posts are very nicely written and helped me a lot in understanding the concepts.

    ReplyDelete