java - 关于java中的join方法

标签 java multithreading

在下面的代码中,主线程将调用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 内存模型并使您面临未定义的行为。

ma​​keItSo() 中的

thisStarter 实例,因此 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/

相关文章:

Java:同时从队列中删除对象。

java - HQL : Getting the primary key of an object

python - OpenMP/Cython 中的空闲线程可以用于并行化工作 block 的剩余部分吗?

c++ - Qt5 应用程序在关闭时崩溃 (QWidget::show)

java - mkdir() 没有创建新目录

java - 使用数据报 UDP 发送和接收确认

java - 可以在完全创建对象之前调用对象方法吗?

java - 在eclipse中找不到作为junit测试运行

java - 一个 Activity 不会向另一个 Activity 发送 Intent

java - 安装 Node.js 应用程序时版本不匹配