为什么 'create' 是异步的?

Why is 'create' asynchronous?

有人告诉我,创建新实例始终是一个异步消息;但我不明白为什么。

例如:

Foo myFoo = new Foo();

在这里,我必须等到构造函数完成并 returns 我的新对象。但是异步不是意味着我独立继续(无需等待)——就像启动一个线程一样?

I was told, that creating a new instance is always an async message;

不,java 构造函数没有暗示同步。无论如何,您可能会在其中遇到并发问题。不保证在构造函数调用后所有字段都被初始化。

Here I will have to wait until the constructor finishes and returns my new object. But doesn't asynchronous mean, that I go on independently (no waiting) - like starting a thread?

不,您不必等待。您可以在另一个线程中访问该对象。

我建议你阅读这篇文章thread

I was told, that creating a new instance is always an async message;

Sorry, I have to say that either you heard it wrong or you were told something that is wrong. But first off, we should get some terminology straight. The term "async" or "asynchronous" means that the invocation returns immediately to the caller. We can easily demonstrate that this is not true with a constructor, with a simple experiment [1]. In other words, the constructor must return for the caller to make any progress.

Starting a thread is indeed asynchronous. The call to Thread.start() returns immediately and at some later point in time the thread actually starts 运行ning and executing the run() method.

1 The Experiment

Consider your class (for illustration only) is like below:

Foo.java

class Foo {
    Foo() throws InterruptedException {
        while (true) {
            System.out.println("not returning yet ...");
            Thread.sleep(2000);
        }
    }
    public static void main(String[] args) throws InterruptedException {
         Foo foo = new Foo();
    }
}

If you compiled and 运行 this class (I used Java 8 on my Mac, but that is not a requirement). As expected, this class 运行s forever producing the output every 2 seconds:

not returning yet ...
not returning yet ...
not returning yet ...
not returning yet ...

Note that the sleep call was added just to make it bearable. You could try this experiment without it, but then your program will overwhelm one of the CPU's by stressing it to 100%.

If, while it is 运行ning, you took a thread dump (for example, by using the command jstack), you see something like below (curtailed for brevity):

"main" #1 prio=5 os_prio=31 tid=0x00007f9522803000 nid=0xf07 
waiting on condition [0x000000010408f000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
    at java.lang.Thread.sleep(Native Method)
    at Foo.<init>(Foo.java:5)
    at Foo.main(Foo.java:9)

Regardless of the state of the thread (RUNNABLE, BLOCKED, WAITING, TIMED_WAITING), you will always see (take various thread dumps to see what this means) you will always see these two lines:

    at Foo.<init>(Foo.java:5)
    at Foo.main(Foo.java:9)

which means that the caller (in this case, the main thread) will never make any progress. And since this constructor never returns, no progress happens.

在构造函数仍在执行时并发访问对象的示例:

public class Demo {

  private volatile int constructionCounter;

  private volatile String string;

  public Demo() throws InterruptedException {

    super();

    assert this.constructionCounter == 0;

    this.constructionCounter++;

    // From this point on, there's no way the constructionCounter can ever be != 1 again, because the constructor will never run more than once, concurrently or otherwise.
    assert this.constructionCounter == 1;

    final Demo newInstance = this;

    Thread t = new Thread( new Runnable() {
        public void run() {
          // Access new instance from another thread.
          // Race condition here; may print "Hello null" or "Hello World" depending on whether or not the constructor already finished.
          System.out.println("Hello " + newInstance.getString());
        }
    });

    t.start();

    this.setString( "World!" );

  }

  public String setString( String str ) {
    this.string = str;
  }

  public String getString() {
    return this.string;
  }
}

请注意,只有当构造函数本身以某种方式将 this 交给另一个线程时,这才有可能。