Join method from the Thread class is an important method and used to impose order on the execution of multiple Threads. The concept of joining multiple threads is very popular in a multithreading interview question. Here is one such question, “You have three threads T1, T2, and T3, How do you ensure that they finish in order T1, T2, T3 ?. This question illustrates the power of the join method on multithreaded programming. Unlike classical thread questions like the difference between the wait and sleep method or solving the producer-consumer problem in Java, This one is a bit tricky.
You can do this by using the join method, by calling T1.join() from T2 and T2.join() from T3. In this case thread, T1 will finish first, followed by T2 and T3. In this Java multithreading tutorial, we will have a closer look at the join method with a simple example.
The idea is to illustrate how the join method works in simple words. By the way from Java 5 onwards you can also use CountDownLatch and CyclicBarrier classes to implement scenarios like one thread is waiting for other threads to finish their task.
Btw, if you are serious about mastering Java multi-threading and concurrency then I also suggest you take a look at the Java Multithreading, Concurrency, and Performance Optimization course by Michael Pogrebinsky on Udemy. It's an advanced course to become an expert in Multithreading, concurrency, and Parallel programming in Java with a strong emphasis on high performance.
You can do this by using the join method, by calling T1.join() from T2 and T2.join() from T3. In this case thread, T1 will finish first, followed by T2 and T3. In this Java multithreading tutorial, we will have a closer look at the join method with a simple example.
The idea is to illustrate how the join method works in simple words. By the way from Java 5 onwards you can also use CountDownLatch and CyclicBarrier classes to implement scenarios like one thread is waiting for other threads to finish their task.
Btw, if you are serious about mastering Java multi-threading and concurrency then I also suggest you take a look at the Java Multithreading, Concurrency, and Performance Optimization course by Michael Pogrebinsky on Udemy. It's an advanced course to become an expert in Multithreading, concurrency, and Parallel programming in Java with a strong emphasis on high performance.
When to use the join method in Java?
As I said join is an important and useful method from Thread class but many times overlooked. Similar to the wait for method, by using the join method, we can make one Thread to wait for another.
The primary use of Thread.join() is to wait for another thread and start execution once that Thread has completed execution or died. Join is also a blocking method, which blocks until the thread on which join has called a die or specified waiting time is over.
By the way, understanding, how to join method works, is not straight forward. Many developers get confused about things like, which thread will wait, which thread will join etc. These points will be clearer when we go through an example of joining multiple Thread in Java using join() method.
The primary use of Thread.join() is to wait for another thread and start execution once that Thread has completed execution or died. Join is also a blocking method, which blocks until the thread on which join has called a die or specified waiting time is over.
By the way, understanding, how to join method works, is not straight forward. Many developers get confused about things like, which thread will wait, which thread will join etc. These points will be clearer when we go through an example of joining multiple Thread in Java using join() method.
Thread Join Example in Java
Here is a simple example of joining two threads using the Thread.join() method. By the way, unlike Thread.sleep() method, join() is not a static method, it needs to be called on a java.lang.Thread object. The current thread, which calls the join method will wait until the thread on which join has called a die or wait at most specified millisecond for this thread to die.
/**
* Sample Java class to illustrate How to join two threads in Java.
* join() method allows you to serialize the processing of two threads.
*/
public class Join {
public static void main(String args[]) throws InterruptedException{
System.out.println(Thread.currentThread().getName() + " is Started");
Thread exampleThread = new Thread(){
public void run(){
try {
System.out.println(Thread.currentThread().getName() + " is Started");
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + " is Completed");
} catch (InterruptedException ex) {
Logger.getLogger(Join.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
exampleThread.start();
exampleThread.join();
System.out.println(Thread.currentThread().getName() + " is Completed");
}
}
Output:
main is Started
Thread-0 is Started
Thread-0 is Completed
main is Completed
public static void main(String args[]) throws InterruptedException{
System.out.println(Thread.currentThread().getName() + " is Started");
Thread exampleThread = new Thread(){
public void run(){
try {
System.out.println(Thread.currentThread().getName() + " is Started");
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + " is Completed");
} catch (InterruptedException ex) {
Logger.getLogger(Join.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
exampleThread.start();
exampleThread.join();
System.out.println(Thread.currentThread().getName() + " is Completed");
}
}
Output:
main is Started
Thread-0 is Started
Thread-0 is Completed
main is Completed
If you look at the above example, the first main thread is started, and then it creates another thread, whose name is "Thread-0" and started it. Since Thread-0 sleeps for 2 seconds, it requires at least 2 seconds to complete and in between main thread called join method on the Thread-0 object.
Because of the join method, now, the main thread will wait until Thread-0 completes its operation or You can say the main thread will join Thread-0. If you look at the output, it confirms this theory.
If you want to learn more about essential thread concepts like joins, inter-thread communication, locking and object sharing then I highly recommend you to join Multithreading and Parallel Computing in Java course on Udemy. It's a great course on essential thread concept in Java.
Important points on Thread.join method
Now we know How to use the join method in Java, it’s time to see some important points about Thread.join() method.
2) Join method throws IntrupptedException if another thread interrupted waiting for thread as a result of join() call.
3) Join is also an overloaded method in Java, three version of join() available, check Javadoc for details.
That’s all on How to join two threads in Java with an example. You can Join multiple threads by using Thread.join() method. Join is particularly useful to make one thread wait for another, or serializing two functions e.g. first load your cache and then start processing the request.
Further Learning
Multithreading and Parallel Computing in Java
Java Concurrency in Practice - The Book
Applying Concurrency and Multi-threading to Common Java Patterns
Java Concurrency in Practice Course by Heinz Kabutz
Related Java multithreading Tutorials from Javarevisited Blog
- How to use countdown Semaphore in Java with example
- Why wait and notify method to get called from the synchronized block in Java
- How synchronization works in Java
- How volatile keyword works in Java
- Java mistake 2 – Mixing static and non-static synchronized methods
- Difference between Runnable and Callable in Java
- 5 Best Courses to learn Multithreading in Java
- 6 Books to learn Concurrency and Threading in Java
- What is happens before in Java Multithreading?
- Difference between atomic, volatile, and synchronized in Java
- How does Exchanger works in Java?
- How to do inter-thread communication in Java
- Difference between Executor and ExecutorService in Java
Nice article on join() method .If you provide more article or information with example on CountDown & Cyclic barrier classes then it would be very useful to us. Thanks
ReplyDelete@Chiranjib, Thanks for liking this comment. By the way I do have couple of post on CountDownLatch and CyclicBarrier, You can check this http://javarevisited.blogspot.com/2012/07/countdownlatch-example-in-java.html and Ofcourse I will be keep sharing on this topic.
ReplyDeleteGiven Q: “You have three threads T1, T2 and T3, How do you ensure that they finish in order T1, T2, T3 ?.
ReplyDeleteGiven A: You can do this by using join method by calling T3.join() from T2 and T2.join() from T1.
Comment : In this case, won't the finishing order be T3, T2 and T1 rather T1, T2 and T3.
@Anonymous, You are absolutely correct. If we join in that sequence order would be T3, T2 and T1.
ReplyDeleteCorrect answer should be T3.T2.T1 means T2.join() from T3 and T1.join() from T2. In this case T1 will finish first followed by T2 and T3.
That's a good question to ask. Can you share some use cases where join can be used ?
ReplyDelete@Anonymous & Javin.. Please find the below code to achieve this...
ReplyDeletepackage saxbean;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ThreadOrdering {
static int NUM_THREADS = 3;
public static void main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(NUM_THREADS);
class MyCallable implements Callable {
private final int threadnumber;
MyCallable(int threadnumber){
this.threadnumber = threadnumber;
}
public Integer call() {
System.out.println("Running thread #" + threadnumber);
return threadnumber;
}
}
List> callables =
new ArrayList>();
for(int i=1; i<=NUM_THREADS; i++) {
callables.add(new MyCallable(i));
}
try {
List> results =
exec.invokeAll(callables);
for(Future result: results) {
System.out.println("Got result of thread #" + result.get());
}
} catch (InterruptedException ex) {
ex.printStackTrace();
} catch (ExecutionException ex) {
ex.printStackTrace();
} finally {
exec.shutdownNow();
}
}
}
And finally the result that you will obtain..
Running thread #1
Running thread #3
Running thread #2
Got result of thread #1
Got result of thread #2
Got result of thread #3
At last I hope you guys want to achieve this same thing.
This doesn't ensure that the threads complete execution in the required order, only that the execution results are fetched in that order. (Try printing the system time before returning in call()).
DeleteI would suggest that you stop confusing people and get your basics right.
Create 3 threads but dont start them, then go as follows
ReplyDeletet1.start();
t1.join();
t2.start();
t2.join();
t3.start();
Thread.join waits for a thread to terminate, so the order is guaranteed
This defeats the point of threading. Only 1 thread will be doing using work at any point in time.
DeleteI was reading this article and i fount it very useful. I have this task:
ReplyDeleteTo start service D, service A and B need to be started
To stop service A, service B, D and C must be stopped first
Service B and C can be started in parallel immediately after A has started. Conversely, they can stop in parallel.
Do you have nay suggestions how can i solve it? I'm new in java so i don't know so much things but any advice, suggestions would be useful.
@ SARAL SAXENA
ReplyDeleteI have doubt on your code, re rewitten below
suppose we execute below code from main method
#1. t1.start();
#2. t1.join();
#3. t2.start();
#4. t2.join();
#5. t3.start();
#6. t3.join();
at #1 t1 started by main thread
at #2 main thread joined after t1, means main thread will wait for t1 to complete
at #3 t2 started by main thread
at #4 main thread joined after t2, means main thread will wait for t2 to complete
so up to line 4 main thread is waiting for both t1 and t2 to finish their execution
but
It doesn't mean that t2 waiting for t1 to complete, and same thing for line 5 and 6
at the end of line 6 main thread is waiting for t1, t2 and t3
So my question is how we can guaranty that t2 will execute after t1 and t3 will execute after t2 , because no where we its written like t3.join() from t2 and t2.join() from t1 ?
@Anonymous
ReplyDeleteDoesn't main thread wait for t1 to finish execution before it even starts t2? So if main starts one thread and waits for it to terminate before starting the next thread, how is the sequence not guaranteed?
public class HelloWorld implements Runnable{
ReplyDeletepublic void run()
{
for(int i=0;i<=5;i++)
{
try{
Thread.sleep(1000);
System.out.println("I am from run() :" +i);
}catch(Exception e){System.out.println(e);}
}
}
public static void main(String []args){
HelloWorld h1=new HelloWorld();
Thread t1=new Thread(h1);
Thread t2=new Thread(h1);
Thread t3=new Thread(h1);
t1.setPriority(10);
t1.start();
try{
System.out.println("t1");
t1.join();
}catch(Exception e){System.out.println(e);}
t2.start();
try{
System.out.println("t2");
t2.join();
}catch(Exception e){System.out.println(e);}
t3.start();
try{
System.out.println("t3");
t3.join();
}catch(Exception e){System.out.println(e);}
System.out.println("I am from main()");
}
}
Hi Javin
ReplyDeletecould you explain the meaning of calling T1.join() from T2 and T2.join() from T3 ? Is it same like calling T1.join() from main ? some code in this regard would be appreciated.
Hello Ankit, understanding join is little bit tricky because they are two key factor, first one is thread object you create e.g. t1 = new Thread(); and second is actually running thread, which executes code inside run() method. so when you call t1.start() then T1 thread start running code inside run() method. Now if you want T1 to start processing after T2, you call t2.join() from run() method of t1? This means the thread which is executing code t2.join(), will wait until thread T2 will finish.
ReplyDeleteIn this case T1 is executing code t2.join() and that's why it will wait until T2 finish, which will start by calling t2.start().
Let me know if you still have any doubt.
while (t1.isAlive()) {
ReplyDeletet1.join();
}
What will happen in this code snippet for thread t1.
Can you please provide example where 3 threads are running T1,T2 and T3. And want to run in same order. How to pass T1 to run method of T2?
ReplyDeleteTO make sure T1, T2 and T3 finishes in same order, you need to call T1.join() in T2, T2.join() in T3 and T3.join() in main thread. The logic here is you need to call join on one thread from run method of another thread. Here, I am providing a sample code. I hope it helps.
ReplyDeleteclass ThreadOrder implements Runnable {
Thread waitOn;
public ThreadOrder(Thread waitOn) {
this.waitOn = waitOn;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " started");
for (int i = 1; i <= 4; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ": " + i);
}
if (waitOn != null) {
try {
waitOn.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " complete");
}
}
public class JoinTest {
public static void main(String[] args) throws InterruptedException {
System.out.println(Thread.currentThread().getName() + " started");
Thread t1 = new Thread(new ThreadOrder(null), "one");
Thread t2 = new Thread(new ThreadOrder(t1), "two");
Thread t3 = new Thread(new ThreadOrder(t2), "three");
t1.start();
t2.start();
t3.start();
for (int i = 1; i <= 4; i++) {
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + ": " + i);
}
t3.join();
System.out.println("main complete");
}
}
your example doesn't give much detail on join as first main thread will run and then the worker thread
ReplyDeletet1.start();
t1.join();
t2.start();
t2.join();
t3.start();
t3.join();
joining sequentially work
ReplyDeletet1.start();
t1.join();
t2.start();
t2.join();
t3.start();
t3.join();