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

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

Thread myThread = new Thread(pObject); 

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

 myThread.start(); 

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

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

 myThread.start(); doSomethingElse(); 

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

现在,我的理解是当调用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(); 

哪里

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

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

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


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

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

run()是你的代码中新线程所做的第一件事,但是新线程首先执行了一些设置工作,并且不能保证新线程在原始线程之前完成任何大量的工作。线程继续调用doSomethingElse()

你认为这里没有保证你是对的。 对multithreading代码的行为做出假设是非常痛苦的根源 – 尽量不要这样做!

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

你已经开始了一个新的主题。 该线程与启动它的线程并行运行,因此顺序可以是:

 pObject.run(); doSomethingElse(); 

要么

 doSomethingElse(); pObject.run(); 

或者,更有可能的是,会有一些交叉。 pObject.run()可以在doSomethingElse()的中间运行,反之亦然,或者在另一个完成之前启动,依此类推。 理解这一点并理解primefaces操作的含义是很重要的,否则你会发现自己遇到了一些非常难以发现的错误。

如果两个或多个线程访问相同的变量,则会更复杂。 在某些情况下,一个线程中的值可能永远不会更新。

我强烈建议:

  1. 除非绝对需要,否则不要使程序multithreading; 和

  2. 如果你这样做,请购买并阅读封面以涵盖Brian Goetz的Java Concurrency in Practice 。