多線程:Join的理解

多線程Join的理解

​ 開發中使用多線程也非常少,之前因爲有一個調取兩個攝像頭獲取每幀進行活體檢測時候,有人給了思路說到Join這個關鍵字,我才仔細的研究了一下這個。以前理解的意思是:使用join關鍵字,就是相當於調用join的線程如果沒有執行完畢,其他線程都處於等待狀態。這就相當是把線程串起來了一樣。看了很多的博客,後面理解的是:那個線程等待掛起,取決與在那個線程上面調用XX.join,並不是影響到所有的線程。

  • 代碼演示(正常線程執行)
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 1; i <= 5; i++) {
                System.out.println("A" + "-" + i);
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 1; i <= 5; i++) {
                System.out.println("B" + "-" + i);
            }
        });
        t1.start();
        t2.start();
    }
console
A-1
B-1
B-2
B-3
B-4
B-5
A-2
A-3
A-4
A-5
  • 當在t2線程前面使用join
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 1; i <= 5; i++) {
                System.out.println("A" + "-" + i);
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 1; i <= 5; i++) {
                System.out.println("B" + "-" + i);
            }
        });
        t1.start();
        t1.join();
        t2.start();
    }
    console
A-1
A-2
A-3
A-4
A-5
B-1
B-2
B-3
B-4
B-5

當在t2線程前面,main線程調用了t1線程的join,所以會讓main線程暫時掛起。從而需要等到t1線程死亡之後纔可以喚醒main線程繼續執行下去

  • 當把join放在t2線程後面
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 1; i <= 5; i++) {
                System.out.println("A" + "-" + i);
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 1; i <= 5; i++) {
                System.out.println("B" + "-" + i);
            }
        });
        Thread t3 = new Thread(() -> {
            for (int i = 1; i <= 5; i++) {
                System.out.println("C" + "-" + i);
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t3.start();
    }
console
    A-1
A-2
B-1
A-3
B-2
A-4
B-3
B-4
B-5
A-5
C-1
C-2
C-3
C-4
C-5

無論執行多次,都可證實一點,在main線程中調用xx.join的時候掛起的是main線程,但是掛起main線程之前的執行的線程不受影響。

Join的源碼

    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");
        }
		//執行時間爲0或者缺省情況
        if (millis == 0) {
            //判斷線程是否處於活動狀態
            while (isAlive()) {
                //調用線程的wait方法
                wait(0);
            }
        } else {
            //判斷線程是否處於活動狀態
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                //調用線程的wait方法
                wait(delay);
                now = System.currentTimeMillis() - base;
           }
        }
    }

wait()的作用是讓當前線程去等待。wait方法是object類中的方法,調用該方法是讓獲得當前對象鎖的線程等待,而在t1.join()時,是在主線程中進行調用了,主線程獲得join方法上的對象鎖。

isAlive()這個方法調用的是t1從Thread類中繼承的native方法,是一種普通的方法調用,所以它判斷的是t1線程是否還存活。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章