join 方法

t.join()方法阻塞调用此方法的线程(calling thread)进入 TIMED_WAITING 状态,直到线程t完成,此线程再继续
如在main线程调用t.join(),则会阻塞main线程直到t线程执行完。

而join()函数参数,当调用为t.join(2000),代表阻塞2000毫秒, 当2000毫秒完后,main线程会向下执行,
但也有例外,join(millis)
如在t线程使用 synchronized时,则必须等到synchronized包裹的代码块执行完并传递的millis毫秒后,t.join()的调用线程才会向下执行。

public class Test {

    public static void main(String[] args) {

        Thread thread = new Thread() {
            @Override
            public void run() {
                super.run();
//                synchronized (currentThread()) {
                    for (int i = 0; i < 5; i ++) {
                        try {
                            sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("休眠" + i);
                    }
                    System.out.println("线程结束");
//                }
            }
        };

        long start = System.currentTimeMillis();
        thread.start();
        try {
            thread.join(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("main线程结束");
        System.out.println(System.currentTimeMillis() - start);

    }
}

输出结果:

main线程结束
1005
休眠0
休眠1
休眠2
休眠3
休眠4
线程结束

将thread.join(1000) 改为2000 时,输出结果如下:
休眠0
main线程结束
2005
休眠1
休眠2
休眠3
休眠4
线程结束

将上面代码synchronized 注释放开后再运行,输出结果如下:
休眠0
休眠1
休眠2
休眠3
休眠4
线程结束
main线程结束
5011

查看join方法源码

    /**
     *  Waits at most millis milliseconds for this thread to  
     * die. A timeout of 0 means to wait forever.    当为0时,会一直阻塞调用join函数的线程,直到调用join函数的对象线程执行完毕
     */
    public final synchronized void join(long millis)    throws InterruptedException {
        // 获取当时系统时间
        long base = System.currentTimeMillis();
        long now = 0;
        if (millis < 0) {
            // 当传过来的入参时间小于0,抛出异常
            throw new IllegalArgumentException("timeout value is negative");
        }
        if (millis == 0) {
            // 当等于0时,只要线程未执行完毕,则一直阻塞
            while (isAlive()) {
                // 当前线程未执行完一直阻塞
                wait(0);
            }
        } else {
            // 当时间大于0
            while (isAlive()) {
                // 当前线程还未执行完,则一直循环获取时间,阻塞调用线程到时间结束
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

注意:
wait()是运行在调用线程的,
如在main线程中调用t.join();
则join()函数的调用线程是main线程,wait()也是运行在main线程的,所以阻塞main线程,
而t才是join()的调用对象线程,isAlive也是判断的t线程是否执行完毕,只有在t线程执行完毕,isAlive才为false

你可能感兴趣的:(join 方法)