Calling the
join
method causes the current thread to pause its execution and move to the "
WAITING" state.
The current thread will wait until the thread (whose instance was used to call the
join
method) finishes its execution before it can be scheduled again by the JVM to resume its execution.
The
join
method is an instance method, so it is necessary to have a reference to a thread instance in order to call it.
public class MainClass {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName() + " (" + Thread.currentThread().threadId() + ") : START");
Runnable myRunnable = new Runnable() {
@Override
public void run() {
System.out.println(
Thread.currentThread().getName() + " (" + Thread.currentThread().threadId() + ") : START");
try {
Thread.sleep(1000); // Simulate some work
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
System.out.println(
Thread.currentThread().getName() + " (" + Thread.currentThread().threadId() + ") : END");
}
};
Thread myThread1 = new Thread(myRunnable, "myJoinThread");
myThread1.start();
try {
myThread1.join(); // Main thread waits for myThread1 to complete
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " (" + Thread.currentThread().threadId() + ") : END");
}
}
Output:
main (1) : START
myJoinThread (19) : START
myJoinThread (19) : END
main (1) : END
In this example, two important points should be noted:
- The
myThread1.join();
statement is executed by the "main" thread.
- The reference used to invoke the
join
method belongs to the "myJoinThread" thread.
As you can see from the program output,
the "
main" thread continued its execution only after the "
myJoinThread" thread completed its execution.
Joining an Already Terminated Thread:
If the current thread "
main" tries to join a thread "
myJoinThread" that has already completed its execution,
the JVM recognizes that the "
myJoinThread" thread has already terminated,
and therefore allows the "
main" thread to continue its execution without waiting.
public class MainClass {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName() + " (" + Thread.currentThread().threadId() + ") : START");
Runnable myRunnable = new Runnable() {
@Override
public void run() {
System.out.println(
Thread.currentThread().getName() + " (" + Thread.currentThread().threadId() + ") : EXECUTING");
}
};
Thread myThread1 = new Thread(myRunnable, "myJoinThread");
myThread1.start();
try {
Thread.sleep(1000); // Give enough time for myThread1 to complete
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
System.out.println("myJoinThread state : " + myThread1.getState());
try {
myThread1.join(); // This will return immediately since thread is already terminated
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " (" + Thread.currentThread().threadId() + ") : END");
}
}
Output:
main (1) : START
myJoinThread (19) : EXECUTING
myJoinThread state : TERMINATED
main (1) : END