【Java多线程与并发】——join

目录

1、join()简介

2、例子

3、底层原理

4、其他方法


1、join()简介

join()方法的作用在一个线程内调用另一个线程实例的join()方法,表示线程在此阻塞,以等待相应的实例执行完成,join()内部是通过wait()方法实现的,因此调用join会自动释放锁

2、例子

public class ThreadDemo extends Thread {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " begin run");
        long startTime = System.currentTimeMillis();
        try {
            //模拟耗时处理
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println(Thread.currentThread().getName() + "执行时间为:" + (endTime - startTime));
        System.out.println(Thread.currentThread().getName() + "end run");
    }
}
public class RunTest {

    public static void main(String[] args) throws InterruptedException {
        Thread.currentThread().setName("主线程");
        System.out.println(Thread.currentThread().getName() + "begin run");
        ThreadDemo threadDemo = new ThreadDemo();
        threadDemo.setName("子线程");
        threadDemo.start();
        //阻塞等待
        threadDemo.join();
        System.out.println(Thread.currentThread().getName() + "end run");
    }

}

 运行结果:

从结果中我们可以看出,主线程调用子线程,当执行到join()方法时,子线程对象进入阻塞队列,待子线程执行完毕后主线程继续执行。

3、底层原理

join()方法源码:

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

    public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;
        
        if (millis < 0) {//若millis小于0则抛出异常
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {//若millis=0
            while (isAlive()) {//判断当前线程是否存活
                wait(0);//永久等待,直到线程销毁
            }
        } else {//millis大于0,阻塞指定时间,若时间过期,线程还未结束,就不等待了
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

从源码可知,当参数millis为0时,while循环使用isAlive()方法判断当前线程是否存活(线程存活是指线程已经启动并且还没有死亡),wait(0)表示永远等待。

注意,我们在源码中看到只有wait()方法,却没看到notify()方法,那么是由谁去唤醒在阻塞池中的线程呢?这个是在jvm中实现的, 一个线程执行结束后会执行该线程自身对象的notifyAll方法。

4、其他方法

  • join(long 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;
            }
        }
    }
  • join(long millis, int nanos):等待最多为millis+1毫秒,最少为1毫秒
    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)) {
            //当nanos大于500微妙时,或者毫秒值=0,则等待时间为millis+1毫秒值,至少为1毫秒
            millis++;
        }

        join(millis);
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章