java并发的Join解析

 当主线程调用子线程的join方法时,主线程进入wait,等待子线程结束或者超过等待时间,然后主线程和子线程又进入了各自的抢占模式

public class TestJoin implements Runnable {

    @Override
    public void run() {
        // synchronized (currentThread()) {
        for (int i = 1; i <= 5; i++) {
            try {
                sleep(1000);//睡眠5秒,循环是为了方便输出信息
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("睡眠" + i);
        }
        System.out.println("TestJoin finished");//t线程结束
    }
    //}

    public static void main(String[] sure) throws InterruptedException {
        Thread t = new Thread(new TestJoin());
        long start = System.currentTimeMillis();
        t.start();
        t.join(3000);//等待线程t 3000毫秒
        Long interval = System.currentTimeMillis()-start;
        System.out.println("Main finished after " + interval);//打印主线程结束
    }
}

可以看到,主线程如果是t.join(3000);则先子线程会打印出3次睡眠,然后主线程等到3000秒超时后继续执行。

如果调用t.join(),不给超时间的话,则主线程会一直等待子线程结束,再继续执行。

下面是join的源码,可以看到写的很明白了“A timeout of {@code 0} means to wait forever.” 

    /**
     * Waits at most {@code millis} milliseconds for this thread to
     * die. A timeout of {@code 0} means to wait forever.
     *
     * <p> This implementation uses a loop of {@code this.wait} calls
     * conditioned on {@code this.isAlive}. As a thread terminates the
     * {@code this.notifyAll} method is invoked. It is recommended that
     * applications not use {@code wait}, {@code notify}, or
     * {@code notifyAll} on {@code Thread} instances.
     *
     * @param  millis
     *         the time to wait in milliseconds
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    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;
            }
        }
    }

同时看看wait(0);是怎么处理的:

public final native void wait(long timeout) throws InterruptedException;

在方法wait的注解上有这么一句话解释了如果wait(0)那就一直等着被notify,不会超时。

If
* {@code timeout} is zero, however, then real time is not taken into
* consideration and the thread simply waits until notified.
* </ul>

猜你喜欢

转载自zhuoyaopingzi.iteye.com/blog/2400579