## Introduction

join() is a method we often use in java that sets the current thread to the WAITTING state and then waits for the calling thread to finish executing or be interrupted.

## Definition

join() is a method defined in Thread, let’s look at his definition.

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18  /** * Waits for this thread to die. * *

An invocation of this method behaves in exactly the same * way as the invocation * *

* {@linkplain #join(long) join}{@code (0)} *
* * @throws InterruptedException * if any thread has interrupted the current thread. The * interrupted status of the current thread is * cleared when this exception is thrown. */ public final void join() throws InterruptedException { join(0); } 

## Application

Let’s see how join is used. Usually we need to call thread B.join() in thread A:

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33  public class JoinThread implements Runnable{ public int processingCount = 0; JoinThread(int processingCount) { this.processingCount = processingCount; log.info("Thread Created"); } @Override public void run() { log.info("Thread " + Thread.currentThread().getName() + " started"); while (processingCount > 0) { try { Thread.sleep(1000); } catch (InterruptedException e) { log.info("Thread " + Thread.currentThread().getName() + " interrupted"); } processingCount--; } log.info("Thread " + Thread.currentThread().getName() + " exiting"); } @Test public void joinTest() throws InterruptedException { Thread t2 = new Thread(new JoinThread(1)); t2.start(); log.info("Invoking join"); t2.join(); log.info("Returned from join"); log.info("t2 status {}",t2.isAlive()); } } 

We call t2.join() in the main thread, then the main thread will wait for t2 to finish execution, we see the following output.

 1 2 3 4 5 6  06:17:14.775 [main] INFO com.javaisland.JoinThread - Thread Created 06:17:14.779 [main] INFO com.javaisland.JoinThread - Invoking join 06:17:14.779 [Thread-0] INFO com.javaisland.JoinThread - Thread Thread Thread-0 started 06:17:15.783 [Thread-0] INFO com.javaisland.JoinThread - Thread Thread Thread-0 exiting 06:17:15.783 [main] INFO com.javaisland.JoinThread - Returned from join 06:17:15.783 [main] INFO com.javaisland.JoinThread - t2 status false 

When the thread has finished executing or has not yet started executing, join() will immediately return.

 1 2  Thread t1 = new SampleThread(0); t1.join(); //returns immediately 

join has two other methods with time parameters.

 1  public final void join(long millis) throws InterruptedException 
 1  public final void join(long millis,int nanos) throws InterruptedException 

If the called thread does not return within the given time, the main thread will continue to execute.

 1 2 3 4 5 6 7 8   @Test public void testJoinTimeout() throws InterruptedException { Thread t3 = new Thread(new JoinThread(10)); t3.start(); t3.join(1000); log.info("t3 status {}", t3.isAlive()); } 

The above example will output.

 1 2 3  06:30:58.159 [main] INFO com.javaisland.JoinThread - Thread Created 06:30:58.163 [Thread-0] INFO com.javaisland.JoinThread - Thread Thread Thread-0 started 06:30:59.172 [main] INFO com.javaisland.JoinThread - t3 status true 

Join() also has a happen-before feature, which is that if thread t1 calls t2.join(), then when t2 returns, all t2’s changes will be visible to t1.

We also mentioned this happen-before rule when we talked about the volatile keyword earlier, Application of Volatile.

Let’s look at the following example.

  1 2 3 4 5 6 7 8 9 10   @Test public void testHappenBefore() throws InterruptedException { JoinThread t4 = new JoinThread(10); t4.start(); // not guaranteed to stop even if t4 finishes. do { log.info("inside the loop"); Thread.sleep(1000); } while ( t4.processingCount > 0); } 

As we run it, we can see that the while loop keeps going even though the variable in t4 has gone to 0.

So if we need to use it in this case, we need to use join(), or some other synchronization mechanism.