在下面的代码中,主线程将调用join()
,主线程将等待子线程完成并打印结果9
。
我的问题是 join()
将使其他线程等待,直到该线程完成。但是,主线程会调用join
,但为什么它会等到子线程完成???
public class Starter extends Thread{
private int x = 2;
public static void main(String[] args) throws Exception{
new Starter().makeItSo();
}
public Starter(){
x = 5;
start();
}
public void makeItSo() throws Exception{
join(); // ??????
x = x - 1;
System.out.println(x);
}
public void run(){x *= 2;}
}
下面的代码是我对join()
的理解,主线程会等到t完成。
Thread t = new Thread(new ThreadDemo());
// this will call run() function
t.start();
// waits for this thread to die
t.join();
System.out.println("Hello");
最佳答案
这里最重要的问题是 start() 不得在构造函数中调用,因为它违反了 Java 内存模型并使您面临未定义的行为。
makeItSo() 中的this 是 Starter 实例,因此 join() 应该让主线程等待直到run()完成。
我没有看到任何竞争机会,但是在 Thread 构造函数中调用 start() 会暴露对 this 的不安全引用,从而违反了 Java 内存模型(Starter)和 x 到另一个线程。您现在面临着未定义的行为,这是非常糟糕且难以调试的。
直观上,有效的语句顺序是:
int x = 2;
x = 5;
x *= 2;
x = x - 1;
System.out.println(x);
每次都会打印9,但是不能保证这一点,因为违反了Java内存模型,因此行为充其量只是可能的而不是确定的。
不要从Thread的构造函数中调用start()。有关更多信息,请参阅 Brian Goetz 的关于安全构建技术的developerWorks 文章: http://www.ibm.com/developerworks/java/library/j-jtp0618/index.html
现在来看另一个例子:
Thread t = new Thread(new ThreadDemo());
// this will call run() function
t.start();
// waits for this thread to die
t.join();
System.out.println("Hello");
其行为类似于:
new ThreadDemo().run();
System.out.println("Hello");
运行t.join()将使线程t上运行的代码表现得就像按顺序内联运行一样。 otherThread.join() 使调用线程等待 otherThread 完成执行。
为了强调,我重复一遍:这里最重要的问题是 start() 不得在构造函数中调用,因为它违反了 Java 内存模型并使您面临未定义的行为。
关于java - 关于java中的join方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33685222/