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")