Let’s look at a case: Xiao Ming and his mother prepare to cook, Xiao Ming is responsible for buying food, and his mother is responsible for cooking. The premise of cooking is that Xiao Ming can’t cook until he comes back from buying food.

In the usual way, we wrote:

// omit try catch catch
new Thread(() -> {
    Thread.sleep(6 _000);
    System.out.println("Back from shopping!");
}, "Xiao Ming").start();

new Thread(() -> {
	Thread.sleep(5 _000);
	System.out.println("Dinner is ready!);
}, "Mother").start();
Copy the code

The actual result:

What happened? Oh, it turned out that our program was executed asynchronously. There was no connection between Xiao Ming and his mother, and the program was executed separately, which caused the above error.

How to solve this problem, please take a look at the following explanation…


The process here is called synchronization, so there are many methods to achieve synchronization, but we will not explain here, we use join to achieve this function……

Thread xiaoMing = new Thread(() -> {
    try {
        Thread.sleep(4 _000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("Back from shopping!");
}, "Xiao Ming");

xiaoMing.start();
xiaoMing.join();

try {
    Thread.sleep(3 _000);
} catch (InterruptedException e) {
    e.printStackTrace();
}
System.out.println("Mother, dinner is ready!");
Copy the code

Running results:

The principle of

The join() method has two overloaded methods,

1: join(long millis) –> indicates that the main thread is ready to execute if it has not finished executing after millis milliseconds.

Join (long millis, int nanos) –> join(long millis, int nanos) –> join(long millis, int nanos) –>

Note: If no parameter is passed, the default parameter is 0


Join the source code

public final synchronized void join(long millis)
    throws InterruptedException {
    long base = System.currentTimeMillis(); // Get the current time
    long now = 0;

    if (millis < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }

    if (millis == 0) { // When the join parameter is 0, the wait method is called to wait indefinitely
        while (isAlive()) {
            wait(0); }}else { // If the argument is passed, it will not wait indefinitely
        while (isAlive()) {
            long delay = millis - now;
            if (delay <= 0) {
                break; } wait(delay); now = System.currentTimeMillis() - base; }}}Copy the code

Join () is a synchronized method that calls wait(). The purpose of this procedure is to make the thread holding the lock wait. Who holds the lock? The main thread is waited () because the main thread called threada.join (), which is equivalent to writing a block of synchronized code in the threada.join () code block. The JVM then calls Lock. notify_all(thread) after the child thread threadA completes execution; Waking the thread that holds the object lock, the main thread, continues execution.