なぜjoinはメインスレッドをブロックするのですか?

使用に参加


前回の記事では、CountDownLatchを紹介しました。ちなみに、Thread!のjoinメソッドを紹介しました。

import java.util.concurrent.TimeUnit; 

/ ** 
 * @author:jiaolian 
 * @date:2021-02-28 21:43に作成
 * @ description:参加テスト
 * @modified By:
 *公式アカウント: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()+ ":最初に実行したい"); 
        }、 "スレッドA"); 
        //スレッドAを開始する
        threadA.start();
        //メインスレッドは子スレッドのロックを保持します。子スレッドはメインスレッドが開始する前にブロックされ、子スレッドが終了した後の通知を待ちます; 
        threadA.join(); 
        System.out.println(Thread.currentThread ().getName()+ "スレッド実行"); 
    } 
}

上記のコードに示すように、JoinTestでスレッドAを開始すると、threadAがjoin()メソッドを呼び出し、メインスレッドはthreadAの実行が終了するのを待ちます。つまり、2秒後、メインスレッドが最後の文を実行し、その結果を次の図に示します。

image.png

ソースコードに飛び込みます。joinメソッドの最下層は実際にはwaitメソッドですが、問題は次のとおりです。明らかに、呼び出し元はスレッドAであり、ブロックできるmianスレッドはthreadAです。ブロックすべきではありません。 ?


問題を証明します。呼び出し元がスレッドAであることは明らかですが、ブロックできるmianスレッドはmianスレッドです。


スレッドの結合ソースコードを参照し、上記のコードを次のように変更します。

import java.util.concurrent.TimeUnit; 

/ ** 
 * @author:jiaolian 
 * @date:2021-02-28 21:43に作成
 * @ description:参加テスト
 * @modified By:
 *公式アカウント:Calling 
 * / 
public class JoinCodeTest { 

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

        MyThread threadA = new MyThread( "Thread A"); 
        //スレッドを開始
        AthreadA.start(); 
        //メインスレッドは子スレッドを保持しますロック、子スレッドはメインスレッドが開始する前にブロックされ、子スレッドが終了した後の通知を待ちます; 
        threadA.join2(0); 
        System.out.println(Thread.currentThread()。getName()+ "スレッド実行" ); 
    }

    プライベート静的クラス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()+ ":最初に実行したい"); 
        } 

        //スレッドソースコードのjoinメソッドをコピーして、スレッドAまたはメインスレッドがブロックされているかどうかをテストしますか?
        public final synchronized void join2(long mills)
                throws InterruptedException { 
            long base = System.currentTimeMillis(); 
            long now = 0; 

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

            isnegative "); if(millis == 0){ 
                while(isAlive()){ 
                    //呼び出し元はスレッドAですが、実際に実行をブロックするのはメインスレッドです!
                    System.out.println(Thread.currentThread()。getName()+ "will block"); 
                    wait(0); 
                } 
            } else { 
                while(isAlive()){ 
                    long delay = mills-now; 
                    if(delay <= 0){ 
                        break; 
                    } 
                    wait(delay); 
                    now = System.currentTimeMillis()-base; 
                }
            } 
        } 
    } 
}

上記のコードに示すように、MyThreadはThreadを継承し、joinソースコードをコピーし、join2にjoinを変更し、join2メソッドに出力ステートメントを追加しました。System.out.println (Thread.currentThread()。getName()+ " 「ブロッキング」)は、スレッドAまたはメインスレッドがブロックされているかどうかをテストするために使用されるため、JoinCodeTestのメインメソッドで、ThreadAはjoin2メソッドを呼び出します。

join2メソッドに入るスレッドがメインスレッドであることがわかります。操作結果を以下に示します!

image.png

ここでは、通常の方法として結合を理解できます。実際にブロックするのは呼び出し元のスレッドではなく、現在実行中のスレッドです。


総括する


本日、結合方法を紹介しました。特に、テストを証明するためにソースコード内のコードをコピーすることは、あなたの役に立つと思います。書き込みは完了していません。同時に、修正が必要な領域がたくさんあります。 。訂正してコメントしていただければ幸いです。よろしければ、よろしくお願いします。注意点、迷子にならないでください、私は[練習と呼ばれる]公開番号であり、練習中にマイクロシグナル[jiaolian123abc]が彼らに話しました。




おすすめ

転載: blog.51cto.com/14883474/2642091