简体   繁体   English

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

[英]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: 我强烈建议:

  1. You don't make your program multi-threaded unless you absolutely need to; 除非绝对必要,否则不要使程序成为多线程。 and

  2. 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.

相关问题 我启动线程时未调用运行。 Java的 - Run is not being called when i start the thread. Java Java:为什么在线程内部没有调用方法? - Java: Why method is not called when inside the thread? 在线程对象上调用 start 时,在线程上设置的优先级无效 - Priorities set on thread has no effect when start is called on the thread object 为什么定义的run()方法没有在Thread的调用中调用? - Why run() method defined is not called on call of start by Thread? 为什么再次调用Thread.start会出现IllegalThreadStateException - Why does an IllegalThreadStateException occur when Thread.start is called again Thread.start()方法永远不会调用run() - run() is never called by Thread.start() method 当一个方法被调用时,哪个线程将在c#和java中运行? - when a method is called , which thread will be run in c# and java? 在 Java 中的线程内调用睡眠时如何启动新线程以继续工作 - How to start new Thread to continue work when Sleep is called within a Thread in Java 为什么从浏览器调用与从 Java 调用时 Cosmos 存储过程的运行方式不同? - Why would a Cosmos stored procedure run differently when called from browser vs. called from Java? 从C(JNI)DLL调用时,Java应用程序不会启动线程 - Java app does not start a thread when called from C (JNI) DLL
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM