线程阻塞(四),join及源码解析

2018-05-18  本文已影响0人  William_hi

有一个笔试题,A、B、C三个线程,怎么保证A执行完后再执行B,B执行完后再执行C。

最简单的就是join 了吧。直接上代码:

public static void main(String[] args) throws InterruptedException {
        PrintThread threadA = new PrintThread("Thread A");
        PrintThread threadB = new PrintThread("Thread B");
        PrintThread threadC = new PrintThread("Thread C");
        threadA.start();
        threadA.join();
        threadB.start();
        threadB.join();
        threadC.start();
    }

    static class PrintThread extends Thread {
        PrintThread(String name) {
            super(name);
        }

        @Override
        public void run() {
            System.out.println(getName() + " start");
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(getName() + " end ...");
        }
    }

执行结果:

Thread A start
Thread A end ...
Thread B start
Thread B end ...
Thread C start
Thread C end ...

那么join是怎么实现的呢?看下源码:

  /**
     * Waits for this thread to die.
     *
     * <p> An invocation of this method behaves in exactly the same
     * way as the invocation
     *
     * <blockquote>
     * {@linkplain #join(long) join}{@code (0)}
     * </blockquote>
     *
     * @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 void join() throws InterruptedException {
        join(0);
    }

注意下注释:等待此线程执行完。

join()方法实际上调用了join(long millis),参数是0,再往下看:

    /**
     * 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;
            }
        }
    }

翻译一下注释:等待millis 毫秒终止线程,假如这段时间内该线程还没执行完,那么结束等待。如果是0,意味着一直等待,知道线程终止。

很明显,有一个while循环使该线程一直停留在阻塞状态,再看一下isAlive()方法:

 /**
     * Tests if this thread is alive. A thread is alive if it has
     * been started and has not yet died.
     *
     * @return  <code>true</code> if this thread is alive;
     *          <code>false</code> otherwise.
     */
    public final native boolean isAlive();

是一个native方法,但是看一下注释:判断该线程是否是正在执行状态,正在执行状态是指已经start了,但是还没结束。

通过不停判断该线程的状态,来决定是不是要wait,线程结束,或者达到指定的延迟时间后,终止代码。

上一篇 下一篇

猜你喜欢

热点阅读