-
Notifications
You must be signed in to change notification settings - Fork 1
YourNote 801: Thread Join
The join() method is used to make one thread wait until another thread finishes its execution.
In simple terms:
"Thread A calls
join()on Thread B, so Thread A will pause and wait until Thread B completes."
Without join(), multiple threads execute independently and the main thread may finish before worker threads complete.
join() ensures:
- Proper execution order
- Synchronization between threads
- Main thread waits for worker threads
- Results are available before continuing
thread.join();The current thread waits until thread terminates.
class MyThread extends Thread {
public void run() {
System.out.println("Worker Thread Started");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Worker Thread Finished");
}
}
public class Main {
public static void main(String[] args) throws Exception {
MyThread t1 = new MyThread();
t1.start();
t1.join(); // Wait for t1 to finish
System.out.println("Main Thread Finished");
}
}Worker Thread Started
Worker Thread Finished
Main Thread Finished
t1.start();
System.out.println("Main Thread Finished");Possible output:
Main Thread Finished
Worker Thread Started
Worker Thread Finished
The main thread does not wait.
class Task extends Thread {
private String name;
public Task(String name) {
this.name = name;
}
public void run() {
System.out.println(name + " started");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
System.out.println(name + " finished");
}
}
public class Main {
public static void main(String[] args) throws Exception {
Task t1 = new Task("Thread-1");
Task t2 = new Task("Thread-2");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("All threads completed");
}
}Thread-1 started
Thread-2 started
Thread-1 finished
Thread-2 finished
All threads completed
Sometimes we don't want to wait forever.
Syntax:
thread.join(milliseconds);Example:
t1.join(2000);Meaning:
Wait at most 2 seconds for t1.
After 2 seconds, the current thread continues whether t1 finishes or not.
class MyThread extends Thread {
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {}
System.out.println("Worker finished");
}
}
public class Main {
public static void main(String[] args) throws Exception {
MyThread t1 = new MyThread();
t1.start();
t1.join(2000);
System.out.println("Main continues");
}
}Main continues
Worker finished
Because main only waited 2 seconds.
When a thread calls:
t1.join();The JVM:
- Checks if
t1is still alive. - If yes, the current thread enters WAITING state.
- When
t1finishes, JVM wakes up waiting threads. - Current thread resumes execution.
Imagine downloading 3 files before creating a report.
download1.start();
download2.start();
download3.start();
download1.join();
download2.join();
download3.join();
generateReport();Without join(), the report may be generated before downloads finish.
sumThread.start();
averageThread.start();
sumThread.join();
averageThread.join();
displayResult();The result is displayed only after all calculations complete.
| Feature | join() | sleep() |
|---|---|---|
| Wait for another thread | Yes | No |
| Wait fixed time | Optional | Yes |
| Synchronization | Yes | No |
| Releases monitor lock | No | No |
| Throws InterruptedException | Yes | Yes |
t1.join();Wait until thread finishes.
Thread.sleep(3000);Wait exactly 3 seconds.
t1.join();
t1.start();Output:
No waiting occurs
Reason:
join() is called before thread starts.
t1.start();
t1.join();worker.start();
worker.join();for(Thread t : threads) {
t.join();
}task1.start();
task2.start();
task3.start();
task1.join();
task2.join();
task3.join();leftTask.start();
rightTask.start();
leftTask.join();
rightTask.join();
mergeResults();- Simple synchronization mechanism
- Easy to understand
- Prevents premature program termination
- Ensures task completion before proceeding
- Useful in parallel processing
- Can block threads unnecessarily
- May reduce concurrency
- Not suitable for complex synchronization
- Better alternatives exist for advanced applications:
- ExecutorService
- CompletableFuture
- CountDownLatch
- ForkJoinPool