Thread.join()方法实现main()方法等待所有子线程执行完成[base jdk8]

代码实现

/**
 * Created by Administrator on 2018/2/3.
 */
public class JoinTest {

    public static void main(String[] args) {
        Thread t1 = new Thread(new MyRunnable(), "t1");
        Thread t2 = new Thread(new MyRunnable(), "t2");
        Thread t3 = new Thread(new MyRunnable(), "t3");

        t1.start();
        /**
         * start second thread after waiting for 2 seconds or if it's finished
         */
        try {
            /**
             * main thread wait 2000ms for wait t1 execute finished
             */
            t1.join(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        t2.start();
        /**
         * start third thread only when first thread is finished
         * t.join() = t.join(0) JDK: A timeout of 0 means to wait forever 意思是永远等待,其实是等到t结束后
         */
        try {
            /**
             * main thread wait t1 execute finished forever
             */
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        t3.start();
        /**
         * let all threads finish execution before finishing main thread
         */
        try {
            /**
             * main thread wait t2 execute finished forever
             */
            t2.join();
            /**
             * main thread wait t3 execute finished forever
             */
            t3.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("All threads are dead, exiting main thread");
    }
}

class MyRunnable implements Runnable {

    @Override
    public void run() {
        System.out.println("Thread started:::" + Thread.currentThread().getName());
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Thread ended:::" + Thread.currentThread().getName());
    }
}

关键剖析

Join可以实现线程的执行顺序,内部具体实现流程分析
try {
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
    }
	
	public final void join() throws InterruptedException {
        join(0);
    }
	
	/**
	* synchronized修饰,获得锁
	*/
	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;
                }
				/**
				* 调用Object的wait()方法会释放锁
				*/
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }
通过不断轮询的方式去观察线程是否还是活动线程
join(0)是不断的询问线程的状态,直到线程销毁join()方法才会结束。
当millis>0时,不在是wait(0),而是wait(delay),delay是还剩余的millis时间。有人会问第一次wait(delay)后不就已经经过这millis的时间,
为什么还会有while执行多次wait(delay)呢?因为这里不仅要考虑wait在delay时间后被唤醒,还要考虑到在delay时间内,被notify唤醒,唤醒后还没有执行到millis的时间,因此要多次调用wait(delay)方法。 
join方法底层调用的是wait方法,但要实现wait的提前是要获得锁,执行到wait方法才可以释放锁,而sleep方法不释放锁。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FeelTouch Labs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值