2012-03-21 57 views
4

我有一个例子对我来说似乎很陌生。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)。 为什么?

回答

10

第二个线程创建错误:

Thread t2 = new Thread(t1); 

我无法通过文件支持,但在Thread.run()源代码,我看到:

if (target != null) { 
    target.run(); 
} 

哪里targetRunnable实例。当Thread完成,它清除target变量:

private void exit() { 
    //... 
    target = null; 

这意味着,当所述第一线程完成(join()法)它清除target和第二线程不执行任何操作。当join()被删除时,两者都访问相同的targett1(争用条件)。

TL; DR

从不创建使用另一个线程实例(即使它实现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(),默认情况下这些都是非守护线程。

又见

+0

非常感谢,我知道这是一个非常糟糕的做法,当然,join()在这里没有任何理由,它只是出于好奇。 – Bax 2012-03-21 08:38:22

0

这是因为当您致电t1.join()时,主线程会等待t1死亡。 当你做到这一点

Thread t2 = new Thread(t1); 

你逝去的t1为目标对象,其run方法被调用。

+1

当我打电话t1.join(),主线程在等待T1死,而不是T1等待 – Bax 2012-03-21 08:35:12

+0

当'主(对#2的讨论) '线程调用't1.join()',那个正在等待的人就是'main'。如果你在调试器中运行它,你会看到't2.start()'也被执行。 – 2012-03-21 08:38:59

+0

对不起,我的错。我错误地写了它,反之亦然。现在更正。 – 2012-03-21 09:20:08

0

添加t2.start();前:

System.out.println("t1 is alive: " + t1.isAlive()); 

如果main线程在等待t1死那么t2.start()不能运行t1run方法。否则,无需等待t1死亡,t2可以运行t1run方法。