为什么我们调用Thread.start()方法反过来调用run方法?

时间:2011-11-08 15:06:36

标签: java multithreading

为什么我们调用线程对象的start()方法然后调用run()方法,为什么不直接调用run()方法?

12 个答案:

答案 0 :(得分:65)

  

[...]为什么我们不直接调用run()方法?

run()方法只是一种普通方法(由覆盖)。与任何其他普通方法一样,直接调用它将导致当前线程执行run()

所有魔法都发生在start()内。 start()方法将导致JVM生成新线程并使新生成的线程执行run()

答案 1 :(得分:24)

如果你直接调用run()方法,它的主体在当前线程的上下文中执行。当您调用start()方法时,将创建一个新线程,并在此新线程中执行run()方法。

答案 2 :(得分:16)

即使以编程方式我们没有创建任何线程,对于每个应用程序,O.S都会创建一个默认线程来用CPU执行其代码。

直接调用run方法将使该run方法在O.S。

给出的主线程中执行

但是创建线程类的目的是确保run方法在不同的线程中执行。除非O.S的线程管理器创建一个线程,否则你的run方法不会在一个单独的线程中执行。要请求O.S创建单独的线程,您必须调用start()方法,该方法将向O.S发送请求以创建线程。一旦O.S创建了一个线程,那么O.S将自动在新创建的线程上下文中调用线程类的run方法。因此,您将提供创建单独线程并在单独线程中执行run方法的目的。

如果你直接调用run方法,那就像O.S不会为你创建任何线程,默认主线程将执行你的run方法。 没有必要为它创建一个单独的线程类!

希望我很清楚。如果您需要更多解释来回答您的问题,请与我们联系。

注意:虽然书籍说JVM创建线程,但内部JVM必须向O.S层的线程管理器驱动程序发送请求,以在其线程池中创建新线程。这就是为什么我在这里使用O.S这个术语比JVM更多。

答案 3 :(得分:10)

  

为什么我们调用线程对象的start()方法来轮流调用   run()方法

不,不。 start()调用操作系统,该操作系统启动一个新线程,(大大简化)调用run()方法。同时start()方法已经返回给它的调用者。它们并不等同。

答案 4 :(得分:9)

Runnable只是一个界面。实现Runnable的类没有什么特别之处,只有run方法。

Thread#start是一个本机实现的方法,它创建一个单独的线程并调用Thread的{​​{1}}方法,在新线程中执行代码。

run实施ThreadRunnable的代码如下所示:

run

如果@Override public void run() { if (target != null) { target.run(); } } 实例是通过将Thread传递给Runnable的构造函数创建的,则会调用Thread的{​​{1}}方法。< / p>

否则,扩展Runnable的类必须覆盖run方法才能使Thread生效。

run上调用start不会创建新主题。

答案 5 :(得分:4)

如果线程已经实例化但未启动,则称其处于新状态
除非在线程的实例上调用start()方法,否则它不会被称为活动。
如果你没有在新创建的线程实例线程上调用start()方法,不被认为是活着的。
如果没有调用start()方法并且在Thread实例上直接调用run()方法,那么 run()方法中的代码将不会单独运行新线程,但它将开始在现有线程中运行

查看示例中的问题

class Multi extends Thread{  
 public void run(){  
  for(int i=1;i<5;i++){  
    try{Thread.sleep(500);}catch(InterruptedException e){System.out.println(e);}  
    System.out.println(i);  
  }  
 }  
 public static void main(String args[]){  
  Multi t1=new Multi();  
  Multi t2=new Multi();  

  t1.run();  
  t2.run();  
 }  
}  

Output:1
       2
       3
       4
       5
       1
       2
       3
       4
       5

正如你在上面的程序中看到的,没有上下文切换,因为这里t1和t2将被视为普通对象而不是线程对象。

答案 6 :(得分:2)

这是由于Java中多线程的设计。

调用start ()将启动一个新线程,并且调用run()方法不会启动新线程。

如果在Thread上调用start()方法,Java虚拟机将调用run()方法,并且两个线程将同时运行 - 当前线程和其他线程或Runnable实现。

查看Thread class

start()方法的源代码
 /**
     * Causes this thread to begin execution; the Java Virtual Machine
     * calls the <code>run</code> method of this thread.
     * <p>
     * The result is that two threads are running concurrently: the
     * current thread (which returns from the call to the
     * <code>start</code> method) and the other thread (which executes its
     * <code>run</code> method).
     * <p>
     * It is never legal to start a thread more than once.
     * In particular, a thread may not be restarted once it has completed
     * execution.
     *
     * @exception  IllegalThreadStateException  if the thread was already
     *               started.
     * @see        #run()
     * @see        #stop()
     */
    public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        group.add(this);
        start0();
        if (stopBeforeStart) {
            stop0(throwableFromStop);
        }
    }

    private native void start0();

在上面的代码中,您看不到run()方法的调用。

private native void start0()负责调用run()方法。 JVM创建与java线程对应的本机线程并调用run()方法。

有关本机方法的源代码,请参阅此问题:

Where to find source code for java.lang native methods?

答案 7 :(得分:1)

我认为你在谈论开始一个线程。如果是这种情况,你不直接调用run方法的原因是你将调用该方法,而不是启动该线程。

答案 8 :(得分:1)

当我们使用start方法然后创建一个新线程,然后将为每个新线程执行run方法内的代码。

使用start方法为每个线程,Stack和本机堆栈创建两个堆栈。

Run方法只是调用execute run方法中的代码,因为运行方法调用不会创建不同的堆栈。

实施例

import java.util.concurrent.TimeUnit;

public class thread implements Runnable{

    /**
     * @param args
     */
    public static void main(String[] args) {
        Thread gg=new Thread(new thread());
        Thread gg1=new Thread(new thread());
        gg.run();
        gg1.start();
        /*gg.start();
        gg1.start();*/

    }

    @Override
    public void run() {
        for(int i=0;i<5;i++)
        {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        System.out.println("Hello..." + i);
        }

    }

}

答案 9 :(得分:0)

如果需要,我们可以调用run()方法,但是如果我们调用run方法,它将只作为普通的Java方法运行。它我们称之为start(),JVM创建一个新线程,并在该线程上执行run方法。

答案 10 :(得分:0)

start()run()方法用于运行线程。run()方法只是一个普通的方法,它被用户覆盖,它将在当前线程上调用。 start()方法间接运行run()方法并创建新线程。

答案 11 :(得分:-1)

不同之处在于,如果我们通过start()方法执行run方法,它会创建一个新线程,我们可以执行run方法,否则run()方法将在JVM创建的线程中执行public static void main()方法。这正是多线程的重点,在新线程上运行不同的操作。