In this program, I have tried to explain how to use join() method by solving a popular multi-threading interview question, how to execute three threads in a order, such that T1 will start first and finished last. In this example, I have create a class called ParallelTask which implements Runnable interface and used to create multiple threads.
In the run() method it first print message that it has started and then just calls join() method to wait for its predecessor thread to die before starting again, after that it prints finished execution. I have make these arrangement so that all thread finish their execution in order T3, T2 and T1.
AfterI create object of Thread T1, I set its predecessor as T2. Similarly I set T3 as predecessor of T2. Since its not guaranteed that when a thread will start after calling start() method, you may see that T3 starts before T2, even if we have called T2.start() prior to T3.start(), but by putting those join() statements, we have guaranteed their execution. There is no way that T2 will finish before T3 and T1 will finish before T2.
You can also check out Core Java Volume 1 - Fundamentals by Cay S. Horstmann to get a good starting overview of several fundamentals of threads and multi-threading.
Now, let me explain you execution of this program. Our program starts by JVM invoking main method() and the thread which executes main method is called main thread. How do you I know that? do you remember those "Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException" exceptions? You can see that Java prints name of thread as "main".
In our main() method we have first create three object of ParallelTask class which is nothing but Runnable. These task will be executed by three threads we will create next. We have given all thread meaningful name to understand output better, its actually best practice to name your threads.
Next, I have set predecessor for each thread, its nothing but another thread object and our ParallelTask has variable predecessor to hold reference of thread to which this thread will join. This is critical to ensure ordering between multiple thread.
Since each thread calls predecessor.join() method, by setting right predecessors you can impose ordering. In our example, threads will start in any order but will do processing such that T3 will finish first, followed by T2 and last by T1.
import java.util.concurrent.TimeUnit;
/**
* Simple Java Program to show how to execute threads in a particular order. You
* can enforce ordering or execution sequence using Thread.join() method in
* Java.
*
* @author Javin Paul
*/public class JoinDemo {
private static class ParallelTask implements Runnable {
private Thread predecessor;
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " Started");
if (predecessor != null) {
try {
predecessor.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " Finished");
}
public void setPredecessor(Thread t) {
this.predecessor = t;
}
}
public static void main(String[] args) {
// we have three threads and we need to run in the
// order T1, T2 and T3 i.e. T1 should start first
// and T3 should start last.
// You can enforce this ordering using join() method
// but join method must be called from run() method
// because the thread which will execute run() method
// will wait for thread on which join is called.
ParallelTask task1 = new ParallelTask();
ParallelTask task2 = new ParallelTask();
ParallelTask task3 = new ParallelTask();
final Thread t1 = new Thread(task1, "Thread - 1");
final Thread t2 = new Thread(task2, "Thread - 2");
final Thread t3 = new Thread(task3, "Thread - 3");
task2.setPredecessor(t1);
task3.setPredecessor(t2);
// now, let's start all three threads
t1.start();
t2.start();
t3.start();
}
}
Output
Thread - 1 Started
Thread - 1 Finished
Thread - 2 Started
Thread - 3 Started
Thread - 2 Finished
Thread - 3 Finished
From the output, you can see that threads have started in different order then the order their start() method has called, this is fine because you don't know which thread will get CPU. It all depends upon mood of thread scheduler, but you can see that threads are finished in correct order. Thread 3 finished first, Thread 2 second and Thread 1 last, the order we wanted. This is achieved by using join() method of java.lang.Thread class. It's very useful method to learn.
Some important points about join method in Java :
That's all about how to join two thread in Java using Thread.join() method. You can use this to impose ordering between multiple thread e.g. suppose you want to start processing when all your caches are loaded. Though there are some concurrency utilities like CylicBarrier and CountDownLatch exists, knowing how it works at join level is very good for any Java developer. Let me know if you have doubt or question about Thread.join() method in Java.
Source: Java67
The Tech Platform
Comments