1

任何人都可以解释为什么这个程序给出输出 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 的值将是不可预测的。

4

4 回答 4

6

这里的执行顺序是固定的,因为调用了join()

  1. 构造函数设置x = 5.
  2. 构造函数调用start又调用run一个新线程。
  3. run执行x *= 5x等于 10。
  4. makeItSo叫做。它调用join,从而等待run结束。
  5. 最后,makeItSo设置x = x-1x等于 9。
于 2013-01-14T16:37:59.593 回答
1

为了真正深入理解这一点,您应该阅读17.4.4 Synchronization Orderjava 语言规范,上面写着:

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()*.
于 2013-01-14T16:44:52.573 回答
0

我相信混淆是由调用 join() 的方式引起的——因为它是从实例方法调用的,就像说 this.join(),其中“this”引用了在 main 方法中创建的 Starter 对象。

这意味着主线程等待 Starter 线程终止,然后减小 x 的值。这是结果非常可预测的方式。

于 2013-10-30T18:06:00.337 回答
0

您首先创建 Starter 对象。在构造函数中你有x = 5. 比你打电话start(),它内部调用run()。运行后您的 x 为 10 ( x *= 2)。您join()等待run()完成,然后将 x 减 1,仅此而已。x 是 9。这里真的没有什么不可预测的。

于 2013-01-14T16:37:07.890 回答