In this code, what does the two joins and break mean? t1.join()
causes t2
to stop until t1
terminates?
Thread t1 = new Thread(new EventThread("e1"));
t1.start();
Thread t2 = new Thread(new EventThread("e2"));
t2.start();
while (true) {
try {
t1.join();
t2.join();
break;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
This question is related to
java
multithreading
A picture is worth a thousand words.
Main thread-->----->--->-->--block##########continue--->---->
\ | |
sub thread start()\ | join() |
\ | |
---sub thread----->--->--->--finish
Hope to useful, for more detail click here
This is a favorite Java interview question.
Thread t1 = new Thread(new EventThread("e1"));
t1.start();
Thread e2 = new Thread(new EventThread("e2"));
t2.start();
while (true) {
try {
t1.join(); // 1
t2.join(); // 2 These lines (1,2) are in in public static void main
break;
}
}
t1.join()
means, t1 says something like "I want to finish first". Same is the case with t2
. No matter who started t1
or t2
thread (in this case the main
method), main will wait until t1
and t2
finish their task.
However, an important point to note down, t1
and t2
themselves can run in parallel irrespective of the join call sequence on t1
and t2
. It is the main/daemon
thread that has to wait.
join()
means waiting for a thread to complete. This is a blocker method. Your main thread (the one that does the join()
) will wait on the t1.join()
line until t1
finishes its work, and then will do the same for t2.join()
.
When thread tA call tB.join() its causes not only waits for tB to die or tA be interrupted itself but create happens-before relation between last statement in tB and next statement after tB.join() in tA thread.
It means program
class App {
// shared, not synchronized variable = bad practice
static int sharedVar = 0;
public static void main(String[] args) throws Exception {
Thread threadB = new Thread(() -> {sharedVar = 1;});
threadB.start();
threadB.join();
while (true)
System.out.print(sharedVar);
}
}
Always print
>> 1111111111111111111111111 ...
But program
class App {
// shared, not synchronized variable = bad practice
static int sharedVar = 0;
public static void main(String[] args) throws Exception {
Thread threadB = new Thread(() -> {sharedVar = 1;});
threadB.start();
// threadB.join(); COMMENT JOIN
while (true)
System.out.print(sharedVar);
}
}
Can print not only
>> 0000000000 ... 000000111111111111111111111111 ...
But
>> 00000000000000000000000000000000000000000000 ...
Always only '0'.
Because Java Memory Model don't require 'transfering' new value of 'sharedVar' from threadB to main thread without heppens-before relation (thread start, thread join, usage of 'synchonized' keyword, usage of AtomicXXX variables, etc).
What does this thread join code mean?
To quote from the Thread.join()
method javadocs:
join()
Waits for this thread to die.
There is a thread that is running your example code which is probably the main thread.
t1
and t2
threads. The two threads start running in parallel.t1.join()
to wait for the t1
thread to finish.t1
thread completes and the t1.join()
method returns in the main thread. Note that t1
could already have finished before the join()
call is made in which case the join()
call will return immediately.t2.join()
to wait for the t2
thread to finish.t2
thread completes (or it might have completed before the t1
thread did) and the t2.join()
method returns in the main thread.It is important to understand that the t1
and t2
threads have been running in parallel but the main thread that started them needs to wait for them to finish before it can continue. That's a common pattern. Also, t1
and/or t2
could have finished before the main thread calls join()
on them. If so then join()
will not wait but will return immediately.
t1.join()
means cause t2 to stop until t1 terminates?
No. The main thread that is calling t1.join()
will stop running and wait for the t1
thread to finish. The t2
thread is running in parallel and is not affected by t1
or the t1.join()
call at all.
In terms of the try/catch, the join()
throws InterruptedException
meaning that the main thread that is calling join()
may itself be interrupted by another thread.
while (true) {
Having the joins in a while
loop is a strange pattern. Typically you would do the first join and then the second join handling the InterruptedException
appropriately in each case. No need to put them in a loop.
let's say our main thread starts the threads t1 and t2. Now, when t1.join() is called, the main thread suspends itself till thread t1 dies and then resumes itself. Similarly, when t2.join() executes, the main thread suspends itself again till the thread t2 dies and then resumes.
So, this is how it works.
Also, the while loop was not really needed here.
Simply put:
t1.join()
returns after t1
is completed.
It doesn't do anything to thread t1
, except wait for it to finish.
Naturally, code following
t1.join()
will be executed only after
t1.join()
returns.
From oracle documentation page on Joins
The
join
method allows one thread to wait for the completion of another.
If t1 is a Thread
object whose thread is currently executing,
t1.join() : causes the current thread to pause execution until t1's thread terminates.
If t2 is a Thread
object whose thread is currently executing,
t2.join(); causes the current thread to pause execution until t2's thread terminates.
join
API is low level API, which has been introduced in earlier versions of java. Lot of things have been changed over a period of time (especially with jdk 1.5 release) on concurrency front.
You can achieve the same with java.util.concurrent API. Some of the examples are
ExecutorService
Executors
(since java 8)Refer to related SE questions:
For me, Join() behavior was always confusing because I was trying to remember who will wait for whom. Don't try to remember it that way.
Underneath, it is pure wait() and notify() mechanism.
We all know that, when we call wait() on any object(t1), calling object(main) is sent to waiting room(Blocked state).
Here, main thread is calling join() which is wait() under the covers. So main thread will wait until it is notified. Notification is given by t1 when it finishes it's run(thread completion).
After receiving the notification, main comes out of waiting room and proceeds it's execution.
Hope it helps!
package join;
public class ThreadJoinApp {
Thread th = new Thread("Thread 1") {
public void run() {
System.out.println("Current thread execution - " + Thread.currentThread().getName());
for (int i = 0; i < 10; i++) {
System.out.println("Current thread execution - " + Thread.currentThread().getName() + " at index - " + i);
}
}
};
Thread th2 = new Thread("Thread 2") {
public void run() {
System.out.println("Current thread execution - " + Thread.currentThread().getName());
//Thread 2 waits until the thread 1 successfully completes.
try {
th.join();
} catch( InterruptedException ex) {
System.out.println("Exception has been caught");
}
for (int i = 0; i < 10; i++) {
System.out.println("Current thread execution - " + Thread.currentThread().getName() + " at index - " + i);
}
}
};
public static void main(String[] args) {
ThreadJoinApp threadJoinApp = new ThreadJoinApp();
threadJoinApp.th.start();
threadJoinApp.th2.start();
}
//Happy coding -- Parthasarathy S
}
Source: Stackoverflow.com