多線程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線程是否還存活。