Java Thread join() — Run Threads in a Specific Order

Java Thread join() — Run Threads in a Specific Order 

The join() method is one of the simplest yet most powerful ways to control thread execution order in Java.

By default, Java threads run asynchronously, meaning:

  • They start immediately

  • They run independently

  • Their execution order is not guaranteed

But in some use cases—such as sequential processing, workflow pipelines, scheduler tasks—you need Thread A → then Thread B → then Thread C.

This is where join() helps.


What Does join() Do? (Simple Explanation)

join() tells the current thread:

“Wait here until the other thread finishes.”

Example:
If t1.join() is called inside the main thread:

main thread waits → until t1 finishes → then continues

So you get guaranteed ordering.


Use Case: Run Threads in Sequence

We want:

Thread 1Thread 2Thread 3

Each thread must start only after the previous one completes.


Full Java Example — Using join()

ThreadJoinExample.java

package threading; /** * This example demonstrates how the Thread join() method works. * * Requirement: * - Thread 2 must start only after Thread 1 completes * - Thread 3 must start only after Thread 2 completes * * We use join() to ensure strict sequential execution. * * @author vinod */ public class ThreadJoinExample { public static void main(String[] args) { Thread t1 = new Thread(new MyThread1()); Thread t2 = new Thread(new MyThread2()); Thread t3 = new Thread(new MyThread3()); try { t1.start(); // Thread 2 will start only after completion of Thread 1 t1.join(); t2.start(); // Thread 3 will start only after completion of Thread 2 t2.join(); t3.start(); } catch (InterruptedException e) { e.printStackTrace(); } } } class MyThread1 implements Runnable { public void run() { System.out.println("Thread1 Started"); } } class MyThread2 implements Runnable { public void run() { System.out.println("Thread2 Started"); } } class MyThread3 implements Runnable { public void run() { System.out.println("Thread3 Started"); } }

Output

Thread1 Started Thread2 Started Thread3 Started

Execution order is guaranteed.


How It Works (Visual Diagram)

main thread │ ├── t1.start() │── wait using t1.join() │ ├── t2.start() │── wait using t2.join() │ └── t3.start()

Timeline:

t1: ──────────────(done) t2: ──────────────(done) t3: ──────────────(done)

When Should You Use join()?

Use join() when you need deterministic ordering:

✔ Workflow steps

Step 1 → Step 2 → Step 3

✔ Dependent tasks

Database migration → Index rebuild → Service restart

✔ Blocking until background work completes

Render UI only after data loads

✔ Waiting for multiple threads (with join() on each)


Important Notes

  • join() blocks the current thread, not the target thread

  • join() can cause performance issues if overused

  • For large-scale concurrency, prefer ExecutorService or Virtual Threads


Interview Tip

Q: What is the difference between start() and run()?

  • start() → creates a new thread

  • run() → executes like a normal method in the same thread

join() only works with start().


No comments:

Post a Comment

12 classic String-based Java interview questions with simple explanations and code.

  1️⃣ Check if a String is a Palindrome Problem Given a string, check if it reads the same forward and backward. Example: "madam...

Featured Posts