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

有一个笔试题,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.
     *
     * 

An invocation of this method behaves in exactly the same * way as the invocation * *

* {@linkplain #join(long) join}{@code (0)} *
* * @throws InterruptedException * if any thread has interrupted the current thread. The * interrupted status 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.
     *
     * 

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 * interrupted status 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  true if this thread is alive;
     *          false otherwise.
     */
    public final native boolean isAlive();

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

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

你可能感兴趣的:(线程阻塞(四),join及源码解析)