Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在java中,当对线程对象调用start()时,为什么不立即调用run()_Java_Multithreading_Runnable - Fatal编程技术网

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

在java中,当对线程对象调用start()时,为什么不立即调用run(),java,multithreading,runnable,Java,Multithreading,Runnable,还是这样? 我有一个线程对象,来自: Thread myThread = new Thread(pObject); 其中pObject是实现Runnable接口的类的对象,然后我对thread对象调用start方法,如下所示: myThread.start(); 现在,我的理解是,当调用start()时,JVM隐式(并立即)调用run()方法,该方法可能被重写(在我的例子中就是这样) 但是,在我的情况下,似乎不会立即(根据需要)调用start()方法,而是直到从调用块完成其他语句/方法,即如

还是这样?
我有一个线程对象,来自:

Thread myThread = new Thread(pObject);
其中pObject是实现Runnable接口的类的对象,然后我对thread对象调用start方法,如下所示:

myThread.start();
现在,我的理解是,当调用start()时,JVM隐式(并立即)调用run()方法,该方法可能被重写(在我的例子中就是这样)

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

myThread.start();
doSomethingElse();
doSomthingElse()在运行run()方法之前执行。
也许我的初始前提是run()总是在start()被调用之后被调用,这是错误的。请帮忙!理想的方法是在start()之后立即执行run()。谢谢。

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


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

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

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

pObject.run();
doSomethingElse();

或者,更有可能的是,会有一些交叉<代码> PbActudi.Run()/<代码>可以在 DoMeToSuthEnter()/代码>的中间运行,反之亦然,或在另一个完成之前启动。理解这一点并理解原子操作的含义是很重要的,否则你会发现自己有一些很难找到的bug

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

我强烈建议:

  • 你不会让你的程序多线程,除非你绝对需要;及

  • 如果你这样做了,买一本,从头读到尾


  • 调用myThread.start()时,线程可供执行。它是否真的会获得CPU,持续多长时间——这取决于操作系统调度程序。事实上,您的
    run()
    可能会立即获得控制权,但在它能做任何您能注意到的事情之前就失去了控制权。确保线程执行
    doSomethingElse()
    之前所需内容的唯一方法是使用显式同步

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

    这是不正确的。它确实隐式调用
    run()
    ,但调用不一定立即发生

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

    要强制线程立即开始运行(或者更准确地说,在
    doSomethingElse()
    之前开始运行),您需要执行一些显式同步;e、 g.类似这样的情况:

        java.util.concurrent.CountDownLatch latch = new CountdownLatch(1);
        new Thread(new MyRunnable(latch)).start();
        latch.await(); // waits until released by the child thread.
        doSomethingElse();
    
    在哪里

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

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



    1-不建议使用
    等待
    /
    通知
    ,但如果并发API不可用,这可能是您的唯一选择;e、 g.在Java ME上。

    在线程对象上调用start方法可能不会使jvm立即调用run()方法,相反,它会使线程成为可运行并准备好执行的线程,在这种情况下,父线程首先执行其代码,然后将控制权传递给子线程,如果您希望在执行父线程代码之前执行子线程,请在父线程中使用chileThreadObject.join()方法。

    +1“对多线程代码的行为进行假设是非常痛苦的根源-尽量不要这样做!”您可以调用
    thread.yield()
    来“释放”其他线程的CPU,但这并不意味着新线程就是下一个线程。“该线程与启动它的线程并行运行…”。不一定。例如,在一个只有一个核心(并且没有超线程)的平台上,两个线程的执行可能是交错的,但它们不可能并行运行。
        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();
        }
        ...
    }