I\'m confused in join()
method used in Threads in Java. In the following code:
// Using join() to wait for threads to finish.
class NewThread im
join() is a instance method of java.lang.Thread class which we can use join() method to ensure all threads that started from main must end in order in which they started and also main should end in last. In other words waits for this thread to die.
Exception: join() method throws InterruptedException.
Thread state: When join() method is called on thread it goes from running to waiting state. And wait for thread to die.
synchronized block: Thread need not to acquire object lock before calling join() method i.e. join() method can be called from outside synchronized block.
Waiting time: join(): Waits for this thread to die.
public final void join() throws InterruptedException;
This method internally calls join(0). And timeout of 0 means to wait forever;
join(long millis) – synchronized method Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever.
public final synchronized void join(long millis)
throws InterruptedException;
public final synchronized void join(long millis, int nanos)
throws InterruptedException;
Example of join method
class MyThread implements Runnable {
public void run() {
String threadName = Thread.currentThread().getName();
Printer.print("run() method of "+threadName);
for(int i=0;i<4;i++){
Printer.print("i="+i+" ,Thread="+threadName);
}
}
}
public class TestJoin {
public static void main(String...args) throws InterruptedException {
Printer.print("start main()...");
MyThread runnable = new MyThread();
Thread thread1=new Thread(runnable);
Thread thread2=new Thread(runnable);
thread1.start();
thread1.join();
thread2.start();
thread2.join();
Printer.print("end main()");
}
}
class Printer {
public static void print(String str) {
System.out.println(str);
}
}
Output:
start main()...
run() method of Thread-0
i=0 ,Thread=Thread-0
i=1 ,Thread=Thread-0
i=2 ,Thread=Thread-0
i=3 ,Thread=Thread-0
run() method of Thread-1
i=0 ,Thread=Thread-1
i=1 ,Thread=Thread-1
i=2 ,Thread=Thread-1
i=3 ,Thread=Thread-1
end main()
Note: calling thread1.join() made main thread to wait until Thread-1 dies.
Let’s check a program to use join(long millis)
First, join(1000) will be called on Thread-1, but once 1000 millisec are up, main thread can resume and start thread2 (main thread won’t wait for Thread-1 to die).
class MyThread implements Runnable {
public void run() {
String threadName = Thread.currentThread().getName();
Printer.print("run() method of "+threadName);
for(int i=0;i<4;i++){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Printer.print("i="+i+" ,Thread="+threadName);
}
}
}
public class TestJoin {
public static void main(String...args) throws InterruptedException {
Printer.print("start main()...");
MyThread runnable = new MyThread();
Thread thread1=new Thread(runnable);
Thread thread2=new Thread(runnable);
thread1.start();
// once 1000 millisec are up,
// main thread can resume and start thread2.
thread1.join(1000);
thread2.start();
thread2.join();
Printer.print("end main()");
}
}
class Printer {
public static void print(String str) {
System.out.println(str);
}
}
Output:
start main()...
run() method of Thread-0
i=0 ,Thread=Thread-0
run() method of Thread-1
i=1 ,Thread=Thread-0
i=2 ,Thread=Thread-0
i=0 ,Thread=Thread-1
i=1 ,Thread=Thread-1
i=3 ,Thread=Thread-0
i=2 ,Thread=Thread-1
i=3 ,Thread=Thread-1
end main()
For more information see my blog:
http://javaexplorer03.blogspot.in/2016/05/join-method-in-java.html
You must understand , threads scheduling is controlled by thread scheduler.So, you cannot guarantee the order of execution of threads under normal circumstances.
However, you can use join()
to wait for a thread to complete its work.
For example, in your case
ob1.t.join();
This statement will not return until thread t
has finished running.
Try this,
class Demo {
Thread t = new Thread(
new Runnable() {
public void run () {
//do something
}
}
);
Thread t1 = new Thread(
new Runnable() {
public void run () {
//do something
}
}
);
t.start(); // Line 15
t.join(); // Line 16
t1.start();
}
In the above example, your main thread is executing. When it encounters line 15, thread t is available at thread scheduler. As soon as main thread comes to line 16, it will wait for thread t
to finish.
NOTE that t.join
did not do anything to thread t
or to thread t1
. It only affected the thread that called it (i.e., the main()
thread).
Edited:
t.join();
needs to be inside the try
block because it throws
the InterruptedException
exception, otherwise you will get an error at compile time. So, it should be:
try{
t.join();
}catch(InterruptedException e){
// ...
}
No words just running code
// Thread class
public class MyThread extends Thread {
String result = null;
public MyThread(String name) {
super(name);
}
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("Hello from " + this.getName());
}
result = "Bye from " + this.getName();
}
}
Main Class
public class JoinRND {
public static void main(String[] args) {
System.out.println("Show time");
// Creating threads
MyThread m1 = new MyThread("Thread M1");
MyThread m2 = new MyThread("Thread M2");
MyThread m3 = new MyThread("Thread M3");
// Starting out Threads
m1.start();
m2.start();
m3.start();
// Just checking current value of thread class variable
System.out.println("M1 before: " + m1.result);
System.out.println("M2 before: " + m2.result);
System.out.println("M3 before: " + m3.result);
// After starting all threads main is performing its own logic in
// parallel to other threads
for (int i = 0; i < 1000; i++) {
System.out.println("Hello from Main");
}
try {
System.out
.println("Main is waiting for other threads to get there task completed");
m1.join();
m2.join();
m3.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("M1 after" + m1.result);
System.out.println("M2 after" + m2.result);
System.out.println("M3 after" + m3.result);
System.out.println("Show over");
}
}
I came across the join() while learning about race condition and I will clear the doubts I was having. So let us take this small example
Thread t2 = new Thread(
new Runnable() {
public void run () {
//do something
}
}
);
Thread t1 = new Thread(
new Runnable() {
public void run () {
//do something
}
}
);
t2.start(); //Line 11
t1.start(); //Line 12
t2.join(); //Line 13
t1.join(); //Line 14
System.out.print("<Want to print something that was being modified by t2 and t1>")
My AIM
Three threads are running namely t1, t2 and the main thread. I want to print something after the t1 and t2 has finished. The printing operation is on my main thread therefore for the expected answer I need to let t1 and t2 finish and then print my output.
So t1.join() just makes the main thread wait, till the t1 thread completes before going to the next line in program.
Here is the definition as per GeeksforGeeks:
java.lang.Thread class provides the join() method which allows one thread to wait until another thread completes its execution.
Here is one question that might solve your doubt
Q-> Will t1 thread get the time slice to run by the thread scheduler, when the program is processing the t2.join() at Line 13?
ANS-> Yes it will be eligible to get the time slice to run as we have already made it eligible by running the line t1.start() at Line 11.
t2.join() only applies the condition when the JVM will go to next line, that is Line 14.
It might be also possible that t1 might get finished processing at Line 13.
The JVM and the underlying OS have considerable freedom when scheduling things. The fact that you get all the way to "Waiting for threads to finish" before you see the output from individual threads may simply mean that thread start-up takes a bit longer (i.e. it takes some time between the moment when a thread becomes "alive" and when the run() method actually starts executing). You could conceivably see thread output sooner but it's not guaranteed either way.
As for join(), it only guarantees that whatever is after it will only happen once the thread you are joining is done. So when you have three join() calls in a row it doesn't mean the threads should end in a particular order. It simply means that you will wait for ob1 first. Once ob1 finishes, ob2 and ob3 may be still running or they may already be finished. If they are finished, your other join() calls will return immediately.
synchronized is used specifically when multiple threads access the same object and make changes to it. A synchronized block is guaranteed never to be executed by two threads simultaneously - i.e. the thread that executes it has the synchronized object all to itself.
First rule of threading - "Threading is fun"...
I'm not able to understand the flow of execution of the program, And when ob1 is created then the constructor is called where
t.start()
is written but stillrun()
method is not executed rathermain()
method continues execution. So why is this happening?
This is exactly what should happen. When you call Thread#start
, the thread is created and schedule for execution, it might happen immediately (or close enough to it), it might not. It comes down to the thread scheduler.
This comes down to how the thread execution is scheduled and what else is going on in the system. Typically, each thread will be given a small amount of time to execute before it is put back to "sleep" and another thread is allowed to execute (obviously in multiple processor environments, more than one thread can be running at time, but let's try and keep it simple ;))
Threads may also yield
execution, allow other threads in the system to have chance to execute.
You could try
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
t.start(); // Start the thread
// Yield here
Thread.yield();
}
And it might make a difference to the way the threads run...equally, you could sleep
for a small period of time, but this could cause your thread to be overlooked for execution for a period of cycles (sometimes you want this, sometimes you don't)...
join()
method is used to wait until the thread on which it is called does not terminates, but here in output we see alternate outputs of the thread why??
The way you've stated the question is wrong...join
will wait for the Thread
it is called on to die before returning. For example, if you depending on the result of a Thread
, you could use join
to know when the Thread
has ended before trying to retrieve it's result.
Equally, you could poll the thread, but this will eat CPU cycles that could be better used by the Thread
instead...