Java join() 方法

扫码查看

我有一个对我来说似乎很奇怪的例子。

public class Join {
    public static void main(String[] args) {
        Thread t1 = new Thread(
                new Runnable() {
                    public void run() {
                        System.out.println(Thread.currentThread().getName());
                    }
                }
        );
        Thread t2 = new Thread(t1);
        t1.setName("t1");
        t2.setName("t2");
        t1.start();
        try {t1.join();} catch (InterruptedException ie) {}
        t2.start();
    }
}

我们只会看到打印的 t1。
如果我们将注释“t1.join”,我们将看到预期的输出 (t1 t2)。
为什么 ?

最佳答案

第二个线程创建错误:

Thread t2 = new Thread(t1);

我无法通过文档支持它,但在 Thread.run() 的源代码中我看到:
if (target != null) {
    target.run();
}

其中 targetRunnable 实例。当 Thread 完成后,它会清除 target 变量:
private void exit() {
  //...
  target = null;

这意味着当第一个线程完成时( join() 方法)它会清除 target 并且第二个线程什么都不做。当 join() 被移除时,两者都访问相同的 target t1(竞争条件)。

TL; 博士

永远不要使用另一个线程实例创建线程(即使它实现了 Runnable )。而是创建一个单独的 Runnable 并传递它:
final Runnable run = new Runnable() {
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
};
Thread t1 = new Thread(run, "t1");
Thread t2 = new Thread(run, "t2");  //new Thread(t1, "t2"); is incorrect!
t1.start();
t2.start();

这里不需要任何 join() ,默认情况下这些是非守护进程线程。

也可以看看
  • Java Threading Basics(关于#2 的讨论)
  • 10-06 13:04
    查看更多