Master java skills

Join Method

This is a very important point to note that order of execution of threads is not gauranteed. It is totally up to the Thread scheduler that schedules the threads to run.

  1. Order of execution of threads is not gauranteed
  2. Switching of threads happen in random fashion

For the above mentioned reasons, every time you run a multi threading program, and you may see a different result every time. The task that you want to be executed by multiple threads will be executed but the order is not gauranteed. It is totally upto the thread scheduler how much time it gives to one thread.

Problem without join() method

join() mehod joins execution of one thread to another. Let’s first see the problem without join method.

package com.javatrainingschool;

public class RunnableTask implements Runnable {
	
	public void run() {
		for(int i=0; i < 3; i++) {
			System.out.println(Thread.currentThread().getName() + " : Value of i = " + i);
		}
	}
}
package com.javatrainingschool;

public class ThreadExample {

	public static void main(String[] args) {
		RunnableTask rt1 = new RunnableTask();
		Thread t1 = new Thread(rt1);
		Thread t2 = new Thread(rt1);
		Thread t3 = new Thread(rt1);
		t1.start();
		t2.start();
		t3.start();
	}
	
}
Output :
Thread-0 : Value of i = 0
Thread-2 : Value of i = 0
Thread-1 : Value of i = 0
Thread-1 : Value of i = 1
Thread-2 : Value of i = 1
Thread-0 : Value of i = 1
Thread-2 : Value of i = 2
Thread-1 : Value of i = 2
Thread-0 : Value of i = 2

In the above example, we can see the output is not in any sequence. To overcome this problem, we have join() method.

join() method

join() method causes currently running thread to stop executing until the thread it joins finishes. Since, mostly, it is the main thread that creates user threads, join method pauses main thread so that it doesn’t start another thread until it finishes the first thread on which join() method has been called.

In certain scenarios random execution of threads may be fine, but not in others. If we want, threads to run in a certain order, then we can use join method. join() method makes sure that until one thread finishes, other thread doesn’t start. Let’s understand join() method’s working.

  1. We call join() method on a thread. Let’s assume we have 3 threads and we first called join method on thread t1
  2. So, another thread t2 will join thread t1 after it is finished. Now, we call join() method on thread t2
  3. Now, t3 will join thread t2 when it finishes.

Let’s see one example

join() method example

In the below examle RunnableTask is the same class used above

package com.javatrainingschool;

public class JoinMethodExample {

	public static void main(String[] args) {
		RunnableTask rt1 = new RunnableTask();
		Thread t1 = new Thread(rt1);
		Thread t2 = new Thread(rt1);
		Thread t3 = new Thread(rt1);
		t1.start();
		try {
			t1.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		t2.start();
		try {
			t2.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		t3.start();
	}	
}
Output :
Thread-0 : Value of i = 0
Thread-0 : Value of i = 1
Thread-0 : Value of i = 2
Thread-1 : Value of i = 0
Thread-1 : Value of i = 1
Thread-1 : Value of i = 2
Thread-2 : Value of i = 0
Thread-2 : Value of i = 1
Thread-2 : Value of i = 2

Explanation : In the above output, we can see that the output is in a sequence. When we call t1.join(), t2 will wait before starting until t1 is finished. Similarly, when we call t2.join(), t3 will wait before starting until t2 is finished.

Joining a thread after a certain period of time

There is an overloaded version of join(long milliseconds), which causes currently running thread only for the specified time, and after that it joins the next thread. Let’s say we have – t1.join(3000) – statement. In this case, the next thread will join t1 after 3 seconds. It will not wait for t1 to finish.

Example

RunnableTask class

package com.javatrainingschool;

public class RunnableTask implements Runnable {
	
	public void run() {
		for(int i=0; i < 4; i++) {
			System.out.println("Value of i = " + i);
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
package com.javatrainingschool;

public class JoinMethodExample {

	public static void main(String[] args) {
		RunnableTask rt1 = new RunnableTask();
		Thread t1 = new Thread(rt1);
		Thread t2 = new Thread(rt1);
		Thread t3 = new Thread(rt1);
		t1.start();
		try {
			t1.join(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		t2.start();
		try {
			t2.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		t3.start();
	}	
}
Output :
Value of i = 0 by thread : t1
Value of i = 1 by thread : t1
Value of i = 2 by thread : t1
Value of i = 0 by thread : t2
Value of i = 3 by thread : t1
Value of i = 1 by thread : t2
Value of i = 2 by thread : t2
Value of i = 3 by thread : t2
Value of i = 0 by thread : t3
Value of i = 1 by thread : t3
Value of i = 2 by thread : t3
Value of i = 3 by thread : t3

In the above output, we can see that thread t2 started before t1 is finished. It is because t2 had to wait for only 5 seconds before joining t1. There is a sleep of 2 seonds between each printing of statements.