Java多线程-Thread.join()

Java多线程-Thread.join()

Thread.join()把制定的线程加入到当前线程,可以将两个交替执行的多线程合并为顺序执行的线程。比如在线程B中调用累线程A的join()方法,直到线程A执行完毕后,才会继续执行线程B;

eg:

线程A代码:

public class A extends Thread{

@Override

        public void run() {

           for (int i =0; i <500 ; i++) {

         System.out.println("A--thread:"+i);

           }

}

}

线程B的代码:

public class Bextends Thread {

@Override

    public void run() {

A a =new A();

a.start();

try {

           a.join();// 调用join方法

            for (int i =0; i <500 ; i++) {

         System.out.println("Thread-B:"+i);

}

}catch (Exception e) {

e.printStackTrace();

}

}

public static void main(String[] args){

new B().start();

}

}

观察结果:在线程B的run方法中启动类线程A的start方法和join(),打印的结果没有交叉执行。可以得出上面的结论。感兴趣的同学可以将线程a.join()方法注视掉,观看打印结果有没有交叉执行。   

结论:   当我们调用某个线程的join这个方法时,这个方法会挂起调用线程,直到被调用线程结束执行,调用线程才会继续执行

源码解析:

Thread 源码有3个join方法重载。

public final void join()throws InterruptedException {

join(0);

};

public final synchronized void join(long millis,int nanos)

throws InterruptedException {

if (millis <0) {

throw new IllegalArgumentException("timeout value is negative");

}

if (nanos <0 || nanos >999999) {

throw new IllegalArgumentException(

"nanosecond timeout value out of range");

}

if (nanos >=500000 || (nanos !=0 && millis ==0)) {

millis++;

}

join(millis);

}

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;

}

}

其中

a. join() 和 join(long millis, int nanos) 最后都调用了 join(long millis)。

b. 带参数的 join() 都是 synchronized method。

c. join() 调用了 join(0),从源码可以看到 join(0) 不断检查当前线程(join() 所属的线程实例,非调用线程)是否是 Active。

d. join() 和 sleep() 一样,都可以被中断(被中断时,会抛出 InterrupptedException 异常);不同的是,join() 内部调用了 wait(),会出让锁,而 sleep() 会一直保持锁。


以本文开头的代码为例,我们分析一下代码逻辑:

B 调用 a.join(),a.join() 再调用 a.join(0) (此时 B 会获得 child 实例作为锁,其他线程可以进入 child.join() ,但不可以进入 child.join(0)(同步的), 因为无法获取锁)。child.join(0) 会不断地检查 child 线程是否是 Active。

如果 child 线程是 Active,则循环调用 child.wait(0)(为了防止 Spurious wakeup, 需要将 wait(0) 放入 for 循环体中;此时 B 会释放 a 实例锁,其他线程可以竞争锁并进入 a.join(0)。我们可以得知,可以有多个线程等待某个线程执行完毕)。

一旦 a 线程不为 Active (状态为 TERMINATED), a.join(0) 会直接返回到 a.join(), a.join() 会直接返回到 B 父线程,B 父线程就可以继续运行下去了。

你可能感兴趣的:(Java多线程-Thread.join())