join()是用来保证线程间顺序调度的一个方法,是Thread类的方法。例如在ThreadA中执行了ThreadB.join(),此时ThreadA进入等待状态,直到ThreadB执行结束后才唤醒ThreadA继续执行后续的方法。
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/**
* Package: com.litchi.demo.java
* Date: 2020/5/13
* Desc: 演示join方法调度线程执行
*
* @author liujicheng
*/
class JoinTest {

public static void main(String[] args) {

Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("threadB run start");

try {
//这里sleep为了让threadA开始执行
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
int i = 1 << 6;
while ((i = i >> 1) > 0) {
System.out.println("threadB run i=" + i);
}

System.out.println("threadB finish");
}
});

Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("threadA run start");
try {
System.out.println("threadA call threadB.join()");
threadB.join();
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println("threadA continue");
System.out.println("threadA continue");
System.out.println("threadA finish");

}
});

threadB.start();
threadA.start();
}
}

执行结果:

如果不加join()的执行结果:

这里threadB.join()为什么去执行threadB,因为join()内部是用wait()实现的,所以这里把threadB看作是Object,Object.wait()就是操作当前线程去等待,也就是这里的threadB.join()使得threadA调用Object.wait()方法。

join()的内部实现原理其实是wait()

源码:

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
35
36
37
38
39
40
41
42
43
44
45
/**
* Waits at most {@code millis} milliseconds for this thread to
* die. A timeout of {@code 0} means to wait forever.
*
* <p> This implementation uses a loop of {@code this.wait} calls
* conditioned on {@code this.isAlive}. As a thread terminates the
* {@code this.notifyAll} method is invoked. It is recommended that
* applications not use {@code wait}, {@code notify}, or
* {@code notifyAll} on {@code Thread} instances.
*
* @param millis
* the time to wait in milliseconds
*
* @throws IllegalArgumentException
* if the value of {@code millis} is negative
*
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* <i>interrupted status</i> of the current thread is
* cleared when this exception is thrown.
*/
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;
}
}
}
  • millis小于0抛出IllegalArgumentException异常;
  • millis等于0循环isAlive()判断当前线程是否存活,存活就调用wait(0),把当前线程放入对象的等待集合中,直到对象线程结束才唤醒当前线程;
  • millis大于0 循环isAlive()判断当前线程是否存活,存活就调用wait()传入等待时间,等到时间到后唤醒当前线程的执行。