Use of join method in Java concurrent programming

Introduction

In multi-threaded programming, sometimes the execution of one thread may depend on the execution result of another thread. JDK provides the join method to achieve this function.

When we call the join method on the thread, the calling thread enters the waiting state. It stays in the waiting state until the execution of the referenced thread is completed.

join and its overload method:

  1. join() , wait for the end of the thread execution.
  2. join(long millis) , similar to the join() method, with an additional millis parameter, which indicates the maximum number of milliseconds to wait for the thread to execute. join(0) is equivalent to join().
  3. join(long millis, int nanos) is the same as join(long millis) method, except that the waiting time has higher precision.

Basic use of join method

Waiting for the end of the child thread, the main thread will continue execution:

//java project www.fhadmin.org
public class Demo {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace ();
            }

            System.out.println("Data loading...");
        });

        thread.start();
        thread.join();

        System.out.println("Data loaded");
    }
}

Output result:

loading...
Data loaded

Set the maximum waiting time, after this time, the main thread will continue to execute, instead of waiting for the end of the child thread to execute:

//java project www.fhadmin.org
public class Demo {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace ();
            }

            System.out.println("Data loading...");
        });

        thread.start();
        thread.join(1000);

        System.out.println("Data loaded");
    }
}

Output result:

Data loaded
loading...


Join method source code

The source code of the join method is as follows:

//java project www.fhadmin.org
public final synchronized void join(long millis)throws InterruptedException {
	long base = System.currentTimeMillis();
	long now = 0;

	//The waiting time is less than 0 and throw IllegalArgumentException directly
	if (millis < 0) {
		throw new IllegalArgumentException("timeout value is negative");
	}

	//The waiting time is 0, call wait(0), and wait for the end of the thread. (join(0) is equal to calling wait(0) is equal to calling wait())
	if (millis == 0) {
		while (isAlive()) {
			wait(0);
		}
	} else {
		//When the waiting time is greater than 0, even if it is awakened midway, as long as the waiting time is not exceeded, it will still enter the waiting state.
		while (isAlive()) {
			long delay = millis - now;
			if (delay <= 0) {
				break;
			}
			wait(delay);
			now = System.currentTimeMillis() - base;
		}
	}
}

As can be seen from the source code of the join method, the essence of the join method is to call the wait method of the thread object. When the join method is called, the lock of the thread object needs to be acquired, and then the wait method of the thread object is called. After the thread ends, the thread object is automatically called notifyAll method.

So when we are doing synchronization, we should avoid using the Thread object as the lock object, because this may affect the work of the system API.


Guess you like

Origin blog.51cto.com/14622073/2657019