任何人都可以解释为什么这个程序提供输出9?我猜测“不可预测的行为”作为答案,因为主线程和线程0可以按任何顺序执行。 join()会对主线程本身做什么?
public class Starter extends Thread{
private int x = 2;
public static void main(String[] args) throws Exception{
new Starter().makeItSo();
}
public Starter(){
//Thread main
x=5;
start();
}
public void makeItSo() throws Exception{
//Thread main
join();
x = x-1;
System.out.println(x);
}
public void run(){
//Thread-0
x*= 2;
}
}
主线程启动thread-0并调用run方法。但如果你把SOP放在makeItSo()中,它会说主线程在调用join()之后在那里等待!为什么? 我认为makeItSo()或run()之间没有序列,所以X的值将是不可预测的。
答案 0 :(得分:6)
此处的执行顺序是固定的,因为调用join()
:
x = 5
。start
,然后在新线程中调用run
。run
执行x *= 5
,使x
等于10。makeItSo
被调用。它会调用join
,从而等待run
结束。makeItSo
设置x = x-1
,使x
等于9。答案 1 :(得分:1)
为了真正深入理解这一点,您应该阅读java语言规范中的17.4.4 Synchronization Order
,其中包含:
Synchronization actions induce the _synchronized-with_ relation on actions,
defined as follows:
...
- An action that starts a thread _synchronizes-with_ the first action in the
thread it starts.
...
- The final action in a thread *T1* _synchronizes-with_ any action in another
thread *T2* that detects that *T1* has terminated. *T2* may accomplish this
by calling *T1.isAlive()* or *T1.join()*.
答案 2 :(得分:0)
首先创建Starter对象。在构造函数中,您有x = 5
。比拨打start()
,而内部呼叫run()
。运行后你的x是10(x *= 2
)。你的join()
等待run()
完成,之后你将x递减1,就是这样。 x是9.这里真的没什么不可预知的。
答案 3 :(得分:0)
我认为混淆是由调用join()的方式引起的 - 因为它是从实例方法调用的,就像在说this.join(),其中'this'引用在main中创建的Starter对象方法
这意味着主线程等待Starter线程终止,之后它会减少x的值。这是结果非常可预测的方式。