What does this thread join code mean?

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();
   }
}

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.

  1. The main thread creates and starts the t1 and t2 threads. The two threads start running in parallel.
  2. The main thread calls t1.join() to wait for the t1 thread to finish.
  3. The 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.
  4. The main thread calls t2.join() to wait for the t2 thread to finish.
  5. The 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.


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().


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


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.

All actions in a thread happen-before any other thread successfully returns from a join() on that 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).