10.线程间通信:join

假设有这样一个场景,在主线程中我们启动了一个子线程做复杂运算,因为比较耗时,主线程会先于子线程结束。现在我们想在主线程中获得子线程的结果,该怎么办呢?我们可能会想到用sleep()可以让主线程休眠,等子线程执行完了,再继续主线程的执行,但是休眠多久这是完全不知道的。我们可以使用join()方便地实现这个功能。

1.初识join

join让执行该行代码的线程进入阻塞状态,直到调用join方法的对象代表的线程执行完毕。举个例子就明白了,主线程中,启动了子线程myThread,myThread.join()将会阻塞主线程,直到myThread执行完毕(正常结束OR发生异常)。
子线程

public class MyThread extends Thread{
    @Override
    public void run() {
        int time = (int)Math.random()*5000;
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("MyThread执行完了。");
    }
}

主线程

public class Main {
    public static void main(String[] args) throws InterruptedException {
        MyThread myThread = new MyThread();
        myThread.start();
        //join阻塞当前线程,只有目标线程myThread正常执行完成了,才能继续向下执行
        myThread.join();
        System.out.println("我会在MyThread执行完成后执行");
    }
}

2.注意事项

  1. join(2000),表示阻塞当前线程最长2s,如果2s内目标线程未执行完,主线程将继续运行
  2. join与interrupt()相遇,将会抛出异常(PS:之前已经说过sleep wait与interrupt相遇也会抛出异常)。比如对于上面的主线程,在因为join而阻塞的期间内,如果我启动另一个线程调用主线程的interrupt,将会抛出异常。
  3. join内部是通过wait(int time)实现的,没有notify,只会因为超时而结束wait,因为wait()会释放占用的锁,所以join也会释放占用的锁
  4. 对于文章开头提到的那个需求,主线程需要获得子线程的执行结果,更好的做法是使用JUC的Callable;对于join的主要作用(等待其他线程结束,当前线程才能继续运行),可以使用JUC的CountDownLatch,比join更加灵活。

你可能感兴趣的:(10.线程间通信:join)