为什么在java中的线程对象上调用start()时不会立即调用run()

pi.*_*pi. 7 java multithreading runnable

或者是吗?
我有一个线程对象来自:

Thread myThread = new Thread(pObject);
Run Code Online (Sandbox Code Playgroud)

其中pObject是实现Runnable接口的类的对象,然后我在线程对象上调用start方法,如下所示:

myThread.start();
Run Code Online (Sandbox Code Playgroud)

现在,我的理解是,当调用start()时,JVM隐式(并立即)调用run()方法,该方法可能被覆盖(就像我的情况一样)

但是,在我的情况下,似乎没有立即调用start()方法(根据需要),但直到从调用块完成其他语句/方法,即如果我在start()调用之后有一个方法,如下所示:

myThread.start();
doSomethingElse();
Run Code Online (Sandbox Code Playgroud)

doSomthingElse()在run()方法运行之前执行.
也许我错误的初始前提是run()总是在调用start()之后调用.请帮忙!再次想要的是在start()之后立即执行run().谢谢.

Mic*_*rdt 16

嗯...该run()方法将在不同的线程中运行.根据定义,这意味着您不能对它将执行的当前线程中的语句之前或之后做出任何假设,除非您明确地同步它们.


Ric*_*dle 13

run()这是新线程在代码中的第一件事,但新线程首先做了一些设置工作,并且无法保证在原始线程继续之前新线程将完成大量工作打电话doSomethingElse().

你认为这里没有任何保证你是对的.对多线程代码的行为做出假设是很痛苦的根源 - 尽量不要这样做!


Ste*_*n C 11

现在,我的理解是,当调用start()时,JVM隐式(并立即)调用run()方法......

那是不对的.它隐式调用run(),但调用不一定立即发生.

实际情况是,新线程可以在start()呼叫发生后的某个时间点进行调度.实际调度由本机调度程序决定.它可以立即发生,或者父线程可以在调度子线程之前继续一段时间.

要强制您的线程立即开始运行(或者更准确,以前开始运行doSomethingElse()),您需要进行一些显式同步; 例如:

    java.util.concurrent.CountDownLatch latch = new CountdownLatch(1);
    new Thread(new MyRunnable(latch)).start();
    latch.await(); // waits until released by the child thread.
    doSomethingElse();
Run Code Online (Sandbox Code Playgroud)

哪里

class MyRunnable implements Runnable {
    private CountDownLatch latch;
    MyRunnable (CountDownLatch latch) { this.latch = latch; }
    public void run() {
        doSomeStuff();
        latch.countDown(); // releases the parent thread
        doSomeMoreStuff();
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

还有其他方法可以使用并发类或Java的互斥/等待/通知原语实现同步1.但是,两个线程之间的显式同步是保证所需行为的唯一方法.

请注意,doSomething()在子线程调用将完成释放父线程之前,但我们可以说一无所知的执行顺序doSomethingElese()doSomeMoreStuff().(一个可能在另一个之前运行,反之亦然,或者它们可能并行运行.)


1 - 不建议使用wait/ notify,但如果并发API不可用,它可能是您唯一的选择; 例如,在Java ME上.


atz*_*tzz 6

当您调用时myThread.start(),您的线程可以执行.它是否会实际获得CPU,以及多长时间 - 它是OS调度程序.事实上,你run()可能会立即获得控制权,但在它可以做任何你能注意到的事情之前就失去它.确保线程执行之前所需的唯一方法doSomethingElse()是使用显式同步.