Why does join block the main thread?

join use


In the last article, we introduced CountDownLatch, and by the way, the join method in Thread!

import java.util.concurrent.TimeUnit; 

/** 
 * @author :jiaolian 
 * @date :Created in 2021-02-28 21:43 
 * @description: join test 
 * @modified By: 
 * Official account : Calling 
 */ 
public class JoinTest { 

    public static void main(String[] args) throws InterruptedException { 
        Thread threadA = new Thread(()->{ 
            try { 
                TimeUnit.SECONDS.sleep(2); 
            } catch (InterruptedException e) { 
                e.printStackTrace( ); 
            } 
            System.out.println(Thread.currentThread().getName()+":Want to execute first"); 
        },"Thread A"); 
        //Start a thread A 
        threadA.start();
        //The main thread will hold the lock of the child thread. The child thread is blocked before the main thread starts, waiting for the notification when the child thread ends; 
        threadA.join(); 
        System.out.println(Thread.currentThread().getName( )+ "Thread execution"); 
    } 
}

As shown in the code above: start a thread A in JoinTest, threadA calls the join() method, and the main thread will wait for threadA to finish executing! That is, two seconds later, the main thread executes the last sentence, and the result is shown in the figure below!

image.png

We dive into the source code. The bottom layer of the join method is actually a wait method, but the question now is: obviously the caller is thread A, and the mian thread that can be blocked is threadA, shouldn't it be blocked?


Prove the problem: it is clear that the caller is thread A, but the mian thread that can be blocked is the mian thread.


We refer to the join source code in Thread and modify the above code as follows:

import java.util.concurrent.TimeUnit; 

/** 
 * @author :jiaolian 
 * @date :Created in 2021-02-28 21:43 
 * @description: join test 
 * @modified By: 
 * Official account : Calling 
 */ 
public class JoinCodeTest { 

    public static void main(String[] args) throws InterruptedException { 

        MyThread threadA = new MyThread("Thread A"); 
        //Start a thread A 
        threadA.start(); 
        //The main thread will hold the child threads Lock, the child thread is blocked before the main thread starts, wait for the notification after the child thread ends; 
        threadA.join2(0); 
        System.out.println(Thread.currentThread().getName()+ "Thread execution"); 
    } 

    private static class MyThread extends Thread { 

        public MyThread(String name) {
            super(name);  
        }

        @Override 
        public void run() { 
            try { 
                TimeUnit.SECONDS.sleep(2); 
            } catch (InterruptedException e) { 
                e.printStackTrace(); 
            } 
            System.out.println(Thread.currentThread(). getName()+": want to execute first"); 
        } 

        //Copy the join method in the Thread source code to test whether thread A or main thread is blocked? 
        public final synchronized void join2(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()) { 
                    //Although the caller is thread A, it is the main thread that actually blocks the execution! 
                    System.out.println(Thread.currentThread().getName()+"will block"); 
                    wait(0); 
                } 
            } else { 
                while (isAlive()) { 
                    long delay = millis-now; 
                    if (delay <= 0) { 
                        break; 
                    } 
                    wait(delay); 
                    now = System.currentTimeMillis()-base;  
                }
            } 
        } 
    } 
}

As shown in the code above: MyThread inherits Thread, copied the join source code, modified join to join2, and added an output statement to the join2 method, System.out.println(Thread.currentThread().getName()+" will "Blocking") is used to test whether thread A or main thread is blocked, so in the main method of JoinCodeTest, ThreadA calls the join2 method.

It turns out that the thread that enters the join2 method is the main thread. The result of the operation is shown in the figure below!

image.png

Here you can understand join as an ordinary method! It is not the caller thread that really blocks, but the thread that is currently executing.


to sum up


Today we introduced the join method , especially copying the code in the source code to prove the test. I believe that it will be helpful to you. The writing is not complete. At the same time, there are many areas that need to be corrected. I hope you can correct and comment. If you like, please like and pay attention. Point of attention, do not get lost, I was [ called practice ] public number , the Micro Signal [jiaolian123abc] telling them while practicing.




Guess you like

Origin blog.51cto.com/14883474/2642091