我有一个对我来说似乎很奇怪的例子。
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();
}
其中
target
是 Runnable
实例。当 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()
,默认情况下这些是非守护进程线程。也可以看看