Thread.join()在多线程中起什么作用,你知道嘛?

#使用场景

有时候我们在主线程中生成了子线程,如果子线程中有进行大量的耗时操作,主线程会比子线程早结束,这也是没有问题的,但是如果主程序在结束之前需要子线程的处理结果,那么就必须要等子线程结束之后才能结束主线程。这个时候我们就可以用join()方法。

多线程按照自己指定的顺序执行。

例子

线程1:

class OneThread extends Thread {
    public OneThread() {
        super("[OneThread] Thread");
    }
    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name + " start.");
        try {
            for (int i = 0; i < 5; i++) {
                System.out.println(name + " loop at " + i);
                Thread.sleep(1000);
            }
            System.out.println(name + " end.");
        } catch (Exception e) {
            System.out.println("Exception from " + name + ".run");
        }
    }
}

class TwoThread extends Thread {
    BThread bt;

    public TwoThread(BThread bt) {
        super("[Twohread] Thread");
        this.bt = bt;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name + " start.");
        try {
            bt.join();
            System.out.println(name + " end.");
        } catch (Exception e) {
            System.out.println("Exception from " + name + ".run");
        }
    }
  
}

public class TestDemo {
    public static void main(String[] args) {
        String name = Thread.currentThread().getName();
        System.out.println(name + " start.");
        OneThread one = new OneThread();
        TwoThread two = new TwoThread(one);
        try {
            one.start();
            Thread.sleep(2000);
            two.start();
            two.join();
        } catch (Exception e) {
            System.out.println("Exception from main");
        }
        System.out.println(name + " end!");
    }
}

执行结果:

main start. //主线程起动,因为调用了two.join(),要等到two结束了,此线程才能向下执行。 
[OneThread] Thread start.
[OneThread] Thread loop at 0
[OneThread] Thread loop at 1
[TwoThread] Thread start. //线程two启动,因为调用one.join(),等到one结束了才向下执行。 
[OneThread] Thread loop at 2
[OneThread] Thread loop at 3
[OneThread] Thread loop at 4
[OneThread] Thread end.
[TwoThread] Thread end. // 线程TwoThread在one.join();阻塞处起动,向下继续执行的结果 
main end! //线程TwoThread结束,此线程在two.join();阻塞处起动,向下继续执行的结果.   

如果我们去掉: two.join();

public class TestDemo {
    public static void main(String[] args) {
        String name = Thread.currentThread().getName();
        System.out.println(name + " start.");
        OneThread one = new OneThread();
        TwoThread two = new TwoThread(one);
        try {
            one.start();
            Thread.sleep(2000);
            two.start();
           // two.join();
        } catch (Exception e) {
            System.out.println("Exception from main");
        }
        System.out.println(name + " end!");
    }
}

打印结果:

main start. // 主线程起动,因为Thread.sleep(2000),主线程没有马上结束;
[OneThread] Thread start.  //线程BThread起动
[OneThread] Thread loop at 0
[OneThread] Thread loop at 1
main end! // 在sleep两秒后主线程结束,TwoThread执行的one.join();并不会影响到主线程。
[TwoThread] Thread start. //线程two起动,因为调用了one.join(),等到one结束了,此线程才向下执行。
[OneThread] Thread loop at 2
[OneThread] Thread loop at 3
[OneThread] Thread loop at 4
[OneThread] Thread end.  //线程OneThread结束了
[TwoThread] Thread end. // 线程TwoThread在OneThread.join();阻塞处起动,向下继续执行的结果

源码分析

在TwoThread的run方法里,执行了one.join();,进入看一下它的JDK源码:

public final void join() throws InterruptedException {
    join(0);
}

然后进入join(long millis)方法:

public final void join(long millis) throws InterruptedException {
    synchronized(lock) {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                lock.wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                lock.wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }
}


private volatile long nativePeer;

/**
 * Tests if this thread is alive. A thread is alive if it has
 * been started and has not yet died.
 *
 * @return  <code>true</code> if this thread is alive;
 *          <code>false</code> otherwise.
 */
public final boolean isAlive() {
    return nativePeer != 0;
}

@FastNative
public final native void wait(long millis, int nanos) throws InterruptedException;
注意点:
  • 如果线程被生成了,但还未被起动,isAlive()将返回false,调用它的join()方法是没有作用的。将直接继续向下执行。
  • TwoThread类中的run方法中,one.join()是判断one``的active状态,如果one的isActive()方法返回false,在one.join(),这一点就不用阻塞了,可以继续向下进行了。从源码里看,wait方法中有参数,也就是不用唤醒谁,只是不再执行wait`,向下继续执行而已。
  • join()方法中, isAlive()方法的签名是:public final native boolean isAlive(),也就是说isAlive()是判断当前线程的状态,也就是one的状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值