Thread.join()的使用

Posted SonoFelice——棣琦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Thread.join()的使用相关的知识,希望对你有一定的参考价值。

代码清单:

package com.baidu.nuomi.concurrent;

import java.util.concurrent.TimeUnit;

/**
 * Created by sonofelice on 16/6/18.
 */
public class Join {
    public static void main(String[] args) throws Exception{
        Thread previous = Thread.currentThread();
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(new Domino(previous),String.valueOf(i));
            thread.start();
            previous = thread;
        }
        TimeUnit.SECONDS.sleep(5);
        System.out.println(Thread.currentThread().getName() + " terminate.");
    }
    static class Domino implements Runnable{
        private Thread thread;
        public Domino(Thread thread){
            this.thread = thread;
        }
        @Override
        public void run() {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " terminate. ");
        }
    }
}

输出结果如下:

main terminate.
0 terminate. 
1 terminate. 
2 terminate. 
3 terminate. 
4 terminate. 
5 terminate. 
6 terminate. 
7 terminate. 
8 terminate. 
9 terminate. 

Process finished with exit code 0

从上述输出可以看到,每个线程终止的前提是前驱线程的终止,每个线程等待前驱线程终止后,才从join方法返回。

代码中创建了10个线程,0~9,每个线程调用前一个线程的join方法,也就是线程0结束了,线程1才能从join方法中返回,而线程0需要等待main线程结束。

看一下join方法的源码:

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

我们调用的join方法没有传参数,就是漂黄的那一段代码,默认millis=0的。

当线程终止时,会调用线程自身的notifyAll()方法,会通知所有等待在该线程对象上的线程。加锁、循环、处理逻辑。跟上一篇博文中的等待/通知经典范式一致。

 

以上是关于Thread.join()的使用的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 C# 代码在回调到 C++ COM 时会停止,直到 Task.Wait/Thread.Join?

Thread线程join方法自我理解

OpenCV 分配导致 std::thread::join 中的段错误

浅析Thread的join() 方法

浅析 Java Thread.join()

java-Thread.join进行线程通信