One day WHEN I was walking down the street, I came across Thread. Join (), so I went online to look up related information, but I was also confused. After a long time of understanding, I would like to explain my understanding of join() method in the form of a graph.

A, I did

Opening picture:

John

Don’t worry, read it twice! As you can see, after the main thread calls the join() method, the specified thread is caught and queued in the back.

Second, you guess

💡 Q: What is the difference between the results of running without the join() method and those of running with the join() method (how many results might there be, the time of running, the order of output)?

🌱 answer:

type Number of possible outcomes The running speed The output sequence Time complexity (best)
Do not use the join () 6 kinds of Fast (multithreaded out-of-order O(1)
Use the join () A kind of Slow (single thread) The order O(n)
  • After watching this, you may still have some questions:

💡 Q: Why is the number of possible results of not using join() 6? Why is the output order out of order?

🌱 A: Because of multithreading, 1/2/3 threads are executed in order by start(), but some threads may finish first for various reasons, resulting in 6 running results —

123  
132  
213  
231  
321  
312
Copy the code
  • Multithreading is dishonest and difficult (not impossible) to control.

💡 Q: Why does join() slow down?

🌱 A: Because when join() is used, the three threads are pushed to the main thread in order, so they cannot run at the same time, only one by one

Three, to start work

Don’t be lazy, while you’re still young, open your IDE and paste in the following code:

public class TestJoin {
    public static void main(String[] args) {
        John john1 = new John();
        John john2 = new John();
        John john3 = new John();

        try {
            john1.start();
            john1.join();
            john2.start();
            john2.join();
            john3.start();
            john3.join();
        } catch(InterruptedException IE) { IE.printStackTrace(); }}}class John extends Thread {
    @Override
    public void run(a) {
        for (int i = 0; i < 2; i++)
        {
            try
            {
                Thread.sleep(500);
                System.out.println("Current Thread: "
                        + Thread.currentThread().getName());
            }catch(Exception ex){
                System.out.println("Exception has" +
                        " been caught"+ ex); } System.out.println(i); }}}Copy the code

Running results:

Current Thread: Thread-0
0
Current Thread: Thread-0
1
Current Thread: Thread-1
0
Current Thread: Thread-1
1
Current Thread: Thread-2
0
Current Thread: Thread-2
1
Copy the code
  • As you can see, the three miserable threads are pulled to the main thread to execute sequentially.

Now, delete two lines of code:

john2.join();
john3.join();
Copy the code

Run again:

Current Thread: Thread-0
0
Current Thread: Thread-0
1
Current Thread: Thread-1
0
Current Thread: Thread-2
0
Current Thread: Thread-2
1
Current Thread: Thread-1
1
Copy the code
  • As you can see, the john2 and John3 threads are not running in the main thread, so the results are more free and the running time is shorter.

Note here that you must start the thread with the start() method before using the join() method. The thread is not working at all, so why pull over?

Source code analysis:

 /** * waiting for this thread to die */
    public final void join(a) throws InterruptedException {
        join(0);
    }
    
     /**
     * Waits at most {@codeMillis} milliseconds for this thread to die. Millis} milliseconds for this thread to die If the thread does not die within code milliseconds, then the time is up and the thread is ignored. A timeout of {@code0} means to wait forever. * If time code=0, wait forever until the thread dies */
    public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

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

        if (millis == 0) {
            while (isAlive()) {
                wait(0); }}else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break; } wait(delay); now = System.currentTimeMillis() - base; }}}Copy the code

Source code:

  1. Is the join () = join (0)
  2. If the time code millis=0 is infinite wait until the thread dies
  3. NotifyAll if the time is greater than 0, the thread that calls the JOIN method is notified to continue execution regardless of whether the thread dies after the time
public static void main(String[] args) {
        John john1 = new John();
        John john2 = new John();
        John john3 = new John();

        try {
            john1.start();
            john1.join();
            john2.start();
            john2.join(5);
            john3.start();
            john3.join();
        } catch(InterruptedException IE) { IE.printStackTrace(); }}Copy the code

The execution result

Current Thread: Thread-0
0
Current Thread: Thread-0
1
Current Thread: Thread-1
0
Current Thread: Thread-2
0
Current Thread: Thread-1
1
Current Thread: Thread-2
1
Copy the code
  • It can be seen that thread john2 is started 5 milliseconds after thread john2 is joined by the main thread, and thread 3 starts to execute. The use of join() is actually the coordination of threads, the orderly execution of threads, and the control of threads in time scheduling ~

Fourth, the end

At this point, you have mastered the use of the join() method. Don’t ask me what I can do with it, wait until you need its functionality, you won’t have to scramble.

Very serious. You read it to the end. Let’s return to the yield() method (covered elsewhere) :

The yield() method is no different from the join() method. When you yield() to a thread, that thread will try to pause itself to give way to the next queued sibling, which is an unstable process (not always effective, and not always when to continue).

In addition, it’s recommended to study syncronized, wait(), and notify() while you can.

Look at the map. I got it all for you: