[英]Why is run() not immediately called when start() called on a thread object in java
Or is it? 还是?
I have a thread object from: 我有一个来自的线程对象:
Thread myThread = new Thread(pObject);
Where pObject is an object of a class implementing the Runnable interface and then I have the start method called on the thread object like so: 其中pObject是实现Runnable接口的类的对象,然后我在线程对象上调用了start方法,如下所示:
myThread.start();
Now, my understanding is that when start() is called, the JVM implicitly (and immediately) calls the run() method which may be overridden (as it is in my case) 现在,我的理解是,当调用start()时,JVM隐式(立即)调用了run()方法,该方法可能会被覆盖(就我而言)
However, in my case, it appears that the start() method is not called immediately (as desired) but until the other statements/methods are completed from the calling block ie if I had a method after the start() call like so: 但是,在我的情况下,似乎没有立即(按需要)调用start()方法,而是直到从调用块完成其他语句/方法为止,即,如果在start()调用之后我有一个方法,例如:
myThread.start();
doSomethingElse();
doSomthingElse() gets executed before the run() method is run at all. doSomthingElse()在运行run()方法之前就已执行。
Perhaps I am wrong with the initial premise that run() is always called right after the start() is called. 最初的前提是总是在调用start()之后立即调用run()可能使我错了。 Please help!
请帮忙! The desired again is making executing run() right after start().
再次希望在start()之后立即执行run()。 Thanks.
谢谢。
Um... the run()
method will run in a different thread . 嗯...
run()
方法将在另一个线程中运行。 That, per definition, means you cannot make any assumptions about before or after which statements in the current thread it will execute, unless you synchronize them explicitly. 根据定义,这意味着您无法对当前线程将在其之前或之后执行的语句做任何假设,除非您明确地同步它们。
run()
is the first thing within your code that the new thread does, but there's some set-up work that the new thread does first, and there's no guarantee that any significant amount of work will by done by the new thread before the original thread goes on to call doSomethingElse()
. run()
是新线程在代码中执行的第一件事,但是新线程首先要进行一些设置工作,并且不能保证新线程会在原始线程之前完成任何大量工作线程继续调用doSomethingElse()
。
You're right in thinking that there are no guarantees here. 您认为这里没有保证是正确的。 Making assumptions about the behaviour of multithreaded code is the source of much pain - try not to do it!
对多线程代码的行为进行假设是造成很多痛苦的根源,请不要这样做!
Now, my understanding is that when start() is called, the JVM implicitly (and immediately) calls the run() method ...
现在,我的理解是,当调用start()时,JVM隐式(立即)调用了run()方法。
That is incorrect. 那是不对的。 It does implicitly call
run()
, but the call does not necessarily happen immediately. 它确实隐式调用
run()
,但调用不一定立即发生。
The reality is that the new thread becomes available to be scheduled at some point in time after the start()
call is made. 现实情况是,在进行
start()
调用后的某个时间点,可以安排新线程使用。 The actual scheduling is up to the native scheduler. 实际调度取决于本机调度程序。 It could happen immediately, or the parent thread could continue for a period before the child thread is scheduled.
它可能立即发生,或者在安排子线程之前,父线程可能会持续一段时间。
To force your thread to start running immediately (or to be more accurate, to start running before doSomethingElse()
), you need to do some explicit synchronization; 为了强制您的线程立即开始运行(或更准确地说,是在
doSomethingElse()
之前开始运行),您需要进行一些显式的同步。 eg something like this: 例如这样的事情:
java.util.concurrent.CountDownLatch latch = new CountdownLatch(1);
new Thread(new MyRunnable(latch)).start();
latch.await(); // waits until released by the child thread.
doSomethingElse();
where 哪里
class MyRunnable implements Runnable {
private CountDownLatch latch;
MyRunnable (CountDownLatch latch) { this.latch = latch; }
public void run() {
doSomeStuff();
latch.countDown(); // releases the parent thread
doSomeMoreStuff();
}
...
}
There are other ways to implement the synchronization using the concurrency classes, or Java's mutex / wait / notify primitives 1 . 还有其他方法可以使用并发类或Java的互斥/等待/通知原语1实现同步。 But explicit synchronization between the two threads is the only way to guarantee the behavior that you require.
但是,两个线程之间的显式同步是保证所需行为的唯一方法。
Note that the doSomething()
call in the child thread will complete before the parent thread is released, but we can say nothing about the order of execution of doSomethingElese()
and doSomeMoreStuff()
. 请注意,子线程中的
doSomething()
调用将在释放父线程之前完成,但是对于doSomethingElese()
和doSomeMoreStuff()
的执行顺序,我们无能为力。 (One might run before the other and vice versa, or they might run in parallel.) (一个可以在另一个之前运行,反之亦然,或者它们可以并行运行。)
1 - Using wait
/ notify
is not recommended, but it may be your only option if the concurrency APIs are not available; 1-不建议使用
wait
/ notify
,但是如果并发API不可用,则这可能是您唯一的选择; eg on Java ME. 例如在Java ME上。
When you call myThread.start()
, your thread becomes available for execution. 当您调用
myThread.start()
,您的线程可用于执行。 Whether it will actually gain CPU, and for how long -- it's up the the OS scheduler. 它是否会真正获得CPU以及持续多长时间-由OS调度程序决定。 In fact, your
run()
may be getting control immediately, but losing it before it can do anything you can notice. 实际上,您的
run()
可能会立即获得控制权,但是在执行任何您可以注意到的操作之前将其丢失。 The only way to ensure that your thread executes what you need before doSomethingElse()
is to use explicit synchronization. 确保线程在
doSomethingElse()
之前执行所需内容的唯一方法是使用显式同步。
You've started a new thread. 您已开始一个新线程。 That thread runs in parallel to the thread that started it so the order could be:
该线程与启动它的线程并行运行,因此顺序可以是:
pObject.run();
doSomethingElse();
or 要么
doSomethingElse();
pObject.run();
or, more likely, there will be some crossover. 或更可能会有一些交叉。
pObject.run()
may run in the middle of doSomethingElse()
or vice versa or one will start before the other finishes and so on. pObject.run()
可能在doSomethingElse()
的中间运行,反之亦然,或者一个将在另一个完成之前启动,依此类推。 It's important to understand this and understand what is meant by an atomic operation or you will find yourself with some really hard-to-find bugs. 了解这一点并理解原子操作的含义很重要,否则您会发现自己遇到了一些很难发现的错误。
It's even more complicated if two or more threads access the same variables. 如果两个或多个线程访问相同的变量,则更为复杂。 The value in one may never be updated in one thread under certain circumstances.
在某些情况下,一个线程中的值可能永远不会更新。
I highly suggest: 我强烈建议:
You don't make your program multi-threaded unless you absolutely need to; 除非绝对必要,否则不要使程序成为多线程。 and
和
If you do, buy and read from cover to cover Brian Goetz's Java Concurrency in Practice . 如果您愿意,请从封面开始阅读并阅读,以涵盖Brian Goetz的Java Concurrency in Practice 。
在线程对象上调用start方法可能不会使jvm立即执行run()方法,而是使线程成为可运行的并准备执行,在这种情况下,父线程首先执行其代码,然后将控制权传递给子线程线程,如果您希望子线程在执行父线程代码之前执行,请在父线程中使用chileThreadObject.join()方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.