我有一个对我来说很奇怪的例子。
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)。 为什么?
答案 0 :(得分:10)
第二个主题创建错误:
Thread t2 = new Thread(t1);
我无法通过文档支持它,但在Thread.run()
的源代码中,我看到了:
if (target != null) {
target.run();
}
其中target
是Runnable
个实例。完成Thread
后,它会清除target
变量:
private void exit() {
//...
target = null;
这意味着当第一个线程完成(join()
方法)时,它会清除target
,而第二个线程什么都不做。移除join()
后,两者都会访问target
t1
(竞争条件)。
永远不要使用其他线程实例创建线程(即使它实现了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()
,默认情况下这些是非守护程序线程。
答案 1 :(得分:0)
这是因为当您致电t1
时,主线程会等待t1.join()
死亡。
当你这样做时
Thread t2 = new Thread(t1);
您正在传递t1
作为调用run
方法的目标对象。
答案 2 :(得分:0)
在t2.start();
之前添加:
System.out.println("t1 is alive: " + t1.isAlive());
如果main
帖子等待t1
死亡,则t2.start()
无法运行t1
的{{1}}方法。否则,无需等待run
死亡,t1
可以运行t2
的{{1}}方法。