t.join()方法阻塞调用此方法的线程(calling thread)进入 TIMED_WAITING 状态,直到线程t完成,此线程再继续
如在main线程调用t.join(),则会阻塞main线程直到t线程执行完。

而join()函数参数,当调用为t.join(2000),代表阻塞2000毫秒, 当2000毫秒完后,main线程会向下执行,
但也有例外,join(millis)
如在t线程使用 synchronized时,则必须等到synchronized包裹的代码块执行完并传递的millis毫秒后,t.join()的调用线程才会向下执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class Test {

public static void main(String[] args) {

Thread thread = new Thread() {
@Override
public void run() {
super.run();
// synchronized (currentThread()) {
for (int i = 0; i < 5; i ++) {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("休眠" + i);
}
System.out.println("线程结束");
// }
}
};

long start = System.currentTimeMillis();
thread.start();
try {
thread.join(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main线程结束");
System.out.println(System.currentTimeMillis() - start);

}
}

输出结果:

main线程结束
1005
休眠0
休眠1
休眠2
休眠3
休眠4
线程结束

将thread.join(1000) 改为2000 时,输出结果如下:
休眠0
main线程结束
2005
休眠1
休眠2
休眠3
休眠4
线程结束

将上面代码synchronized 注释放开后再运行,输出结果如下:
休眠0
休眠1
休眠2
休眠3
休眠4
线程结束
main线程结束
5011

查看join方法源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* Waits at most <code>millis</code> milliseconds for this thread to
* die. A timeout of <code>0</code> means to wait forever. 当为0时,会一直阻塞调用join函数的线程,直到调用join函数的对象线程执行完毕
*/
public final synchronized void join(long millis) throws InterruptedException {
// 获取当时系统时间
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
// 当传过来的入参时间小于0,抛出异常
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
// 当等于0时,只要线程未执行完毕,则一直阻塞
while (isAlive()) {
// 当前线程未执行完一直阻塞
wait(0);
}
} else {
// 当时间大于0
while (isAlive()) {
// 当前线程还未执行完,则一直循环获取时间,阻塞调用线程到时间结束
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}

注意:
wait()是运行在调用线程的,
如在main线程中调用t.join();
则join()函数的调用线程是main线程,wait()也是运行在main线程的,所以阻塞main线程,
而t才是join()的调用对象线程,isAlive也是判断的t线程是否执行完毕,只有在t线程执行完毕,isAlive才为false