0%

join

前言:Thread.join方法

join()

join()是Thread类的一个方法。根据jdk文档的定义:

public final void join()throws InterruptedException: Waits for this thread to die.

join()方法的作用,是等待这个线程结束;但显然,这样的定义并不清晰。个人认为”Java 7 Concurrency Cookbook”的定义较为清晰:

join() method suspends the execution of the calling thread until the object called finishes its execution.

t.join()方法阻塞调用此方法的线程(calling thread),直到线程t完成,此线程再继续;通常用于在main()主线程内,等待其它线程完成再结束main()主线程。代码如下:

线程类

1
2
3
4
5
6
7
8
9
10
/**
* @author shency
* @description: todo
*/
public class MyThread implements Runnable {
@Override
public void run() {
System.out.println("线程 " + this.toString() + "执行结束");
}
}

Main

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Main {
public static void main(String[] args) throws Exception {
final int num = 10;
Thread[] thread = new Thread[num];
for(int i=0;i<num;i++){
thread[i] = new Thread(new MyThread());
}
for(int i=0;i<num;i++){
thread[i].start();
}
try {
for(int i=0;i<num;i++){
thread[i].join();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Main thread is finished");
}
}

运行结果

image-20200102222717486

如果没有join

image-20200102222727059

源码

1
2
3
public final void join() throws InterruptedException {
join(0);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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时,会进入while(isAlive())循环;即只要子线程是活的,主线程就不停的等待。

我们根据上面解释join()作用时的代码来理解join()的用法!wait()的作用是让“当前线程”等待,而这里的“当前线程”是指当前运行的线程。虽然是调用子线程的wait()方法,但是它是通过“主线程”去调用的;所以,休眠的是主线程,而不是“子线程”!

所以isAlive()判断当前对象(例子中的t对象)是否存活,wait()阻塞的是当前执行的线程(例子中的main方法)

join方法是synchronized,Join方法实现是通过wait()。当main线程调用t.join时候,main线程会获得线程对象t的锁(wait意味着拿到该对象的锁),调用该对象的wait(),直到该对象唤醒main线程,比如退出后。这就意味着main 线程调用t.join时,必须能够拿到线程t对象的锁。

join方法用线程对象调用,如果在一个线程A中调用另一个线程B的join方法,线程A将会等待线程B执行完毕后再执行。

总结

join 方法是一个阻塞方法,用来进行线程之间的交流。线程 A 调用 线程 B 的 join 方法,则线程 A 将阻塞,线程 B 执行结束后 线程 A 开始执行。

-------------本文结束感谢您的阅读-------------