join 是Thread 的方法。
import time, threading
# 假定這是你的銀行存款:
balance = 0
def change_it(n):
# 先存后取,結果應該為0:
global balance
balance = balance + n
balance = balance - n
def run_thread(n):
for i in range(100000):
change_it(n)
t1 = threading.Thread(target=run_thread, args=(5,))
t2 = threading.Thread(target=run_thread, args=(8,))
t1.start()
t2.start()
t1.join()
t2.join()
print(balance)
阻塞當前線程,等待到該線程結束,才開始執行后面語句。
Join之后類似于Java,似乎變成單線程了。
Java 的Join
thread.Join把指定的線程加入到當前線程,可以將兩個交替執行的線程合并為順序執行的線程。比如在線程B中調用了線程A的Join()方法,直到線程A執行完畢后,才會繼續執行線程B。
thread.join(1000); 也可以調用join時候加上一個超時參數,如果目標線程在這段時間到期時候還沒有結束的話,join方法總能返回。
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");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
join 方法是synchronized 修飾的,且調用對象是thread,所以當main線程調用t.join時,main線程會獲得線程對象t的鎖(哪個線程調用synchronized方法 哪個線程獲得鎖,而此處是對象Thread t的對象鎖[join是Thread的方法 ])
調用該對象t的wait(等待時間),直到該對象t喚醒main線程 ,比如退出后。
public class Test {
public static void main(String[] args) {
Thread thread1 = new Thread(){
public void run() {
try {
System.out.println(Thread.currentThread().getName());
Thread.sleep(1000);
System.out.println("thread handle 1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread2 = new Thread(){
public void run() {
try {
System.out.println(Thread.currentThread().getName());
Thread.sleep(1000);
System.out.println("thread handle 2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread1.start();
thread2.start();
try {
thread1.join();
System.out.println("==============>");
thread2.join();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("end");
}
}
為了更清楚的看到結果,可以更改兩個線程的Thread休眠時間。
執行結果有3種:
Thread-0
Thread-1
thread handle 1
thread handle 2
==============>
end
Thread-0
Thread-1
thread handle 1
==============>
thread handle 2
end
Thread-0
Thread-1
thread handle 2
thread handle 1
==============>
end
可以看出2個線程同時啟動,但是結束的順序不一定
如 情況一
Thread0.join() start
Thread0首先執行完
Thread0.join() end
輸入 =======>
Thread1.join() start
Thread1 執行完
Thread1.join() end
System.out.println("end")
情況二
Thread0.join() start
Thread1首先執行完
Thread0執行完
Thread0.join() end
輸入 =======>
Thread1.join() start (isAlive = false 的直接跳過阻塞)
Thread1.join() end
System.out.println("end")
情況三
Thread0.join() start
Thread0首先執行完
Thread1執行完 (2個線程幾乎同時執行完至少比Thread0.join()快)
Thread0.join() end
輸入 =======>
Thread1.join() start (isAlive = false 的直接跳過阻塞)
Thread1.join() end
System.out.println("end")