【问题标题】:Why can't we directly call the run() method?为什么不能直接调用run()方法呢?
【发布时间】:2011-01-28 16:01:16
【问题描述】:

如果一个线程的start()方法在内部调用了run()方法,那为什么不在我们的代码中直接调用run()方法呢?这样做会涉及哪些问题?

【问题讨论】:

  • 这是一个非常基本的问题,可以通过非常基本的互联网搜索来回答...@birryree:这是一个非常不同的问题。
  • 没关系,HB。如果它与编程相关并且之前没有被 here 询问过,那么它属于这里。这样,与编程相关的内容的互联网搜索将被定向到此处,而不是那些狡猾的 AskJeeves/ExpertSexChange 网站。
  • @H.B. - 我链接的问题不同,但答案提供了对start()run() 之间差异的相同见解,就像在这个答案中一样:stackoverflow.com/questions/262816/…
  • @paxdiablo:猜猜这是一个公平的观点。 @birryree:你再次链接到这个问题,但我明白你的意思,还有其他几个问题也有答案可以回答这个问题。

标签: multithreading java-me


【解决方案1】:

start 方法确保代码在新的线程上下文中运行。如果你直接调用run,那么它就像一个普通的方法调用,它会在当前线程的上下文中运行,而不是在新的线程中。 start 方法包含触发新线程的特殊代码; run 显然没有这种能力,因为在你编写run 方法时没有包含它。

【讨论】:

  • 对不起,我看不懂最后一行的意思。我在写 run 方法的时候没有在哪里包含它?
  • @Newcomer,你没有在任何地方包含它——这就是重点。 你不是编写代码让事情在新线程中运行的人。这就是Thread 类的工作,它的JVM 本机代码可以直接处理线程并与底层操作系统交互。由于you 没有在run 中编写特殊代码,因此很明显your 代码不会执行任何这些特殊操作。 start 方法实现了这一点。它会为您拨打run;您只需要担心线程在 JVM 开始为您运行它之后应该做什么。
【解决方案2】:

当我们在线程对象上调用 start() 方法时,start() 方法通过为该线程创建一个新的调用堆栈来启动一个新的执行线程。 start() 使该线程开始执行,Java虚拟机调用该线程的 run() 方法。 如果我们调用 run() 而不是 start() 会怎样:

虽然这是合法的,但是 run() 方法会进入当前调用堆栈,而不是创建一个新的调用堆栈。

例如,如果当前正在执行的方法是 main,那么创建的调用堆栈是:

class MyThread extends Thread
 {
    public void run()
     {
    System.out.println("running");
     }
 }
public class ThreadDemo 
 {
 public static void main (String[] args ) 
   {
    MyThread thread=new MyThread();
    thread.start();       
   }
  }

新线程的调用栈(start() 方法创建了一个新的调用栈) 调用堆栈 - 主线程

class MyThread extends Thread
  {
    public void run()
    {
    System.out.println("running");
    }
 }
 public class ThreadDemo 
 {
   public static void main (String[] args ) 
    {
    MyThread thread=new MyThread();
    thread.run();     
    }

}

run() 方法不会为线程创建新的调用堆栈。 run() 方法进入当前调用栈

【讨论】:

    【解决方案3】:

    调用run同步执行代码;而允许 JVM 通过start 调用run 将允许代码异步执行。

    直接调用run 在可能希望避免线程的测试情况下通常是有益的。

    【讨论】:

      【解决方案4】:

      因为start() 会将其作为一个单独的线程来执行。如果你只是调用run(),那将是你的线程的一部分(即一个函数调用)。

      而且,鉴于您的线程可能是一个等待工作的无限循环,这将是一件坏事。

      【讨论】:

        【解决方案5】:
        class A implements Runnable
        {
            public void run()
            {
                for( int i=0; i<5; i++)
                {
                    System.out.println("Thread-A " +i + " Thread Name: "  +Thread.currentThread().getName());
                }
            }
        }
        class B implements Runnable
        {
            public void run()
            {
                for( int i=0; i<5; i++)
                {
        
                    System.out.println("Thread-B " +i + " Thread Name: "  +Thread.currentThread().getName() );
                }
            }
        }
        
        class MyThread 
        {
            public static void main(String [] args)
            {
                Thread t1 = new Thread(new A());
                Thread t2 = new Thread(new B());
        
                t1.run();
                t2.run();
                System.out.println("**********************************************************");
                t1.start();
                t2.start();
            }
        }
        

        复制并粘贴上面的代码...然后运行它,然后查看输出的差异..

        基本上 run() 只会在当前线程的上下文中执行它的主体(这里是主要的) 但, start() 调用操作系统来创建一个新线程。 start() 将在新创建的线程的上下文中调用 run() 方法。

        【讨论】:

        • 漂亮而简单的例子。
        【解决方案6】:

        直接调用 run 方法将在主线程中运行该代码。 那么就好像你的程序只有一个线程(即操作系统给出的主线程)。

        如果你调用 start 方法,它将调用驱动层线程管理器为你创建一个线程,然后你的 run 函数将被调用。因此,您的 run 方法将在单独的线程中执行。不在主线程中。

        【讨论】:

          【解决方案7】:

          线程背后的想法是在每次新线程开始运行时创建新堆栈。

          从主线程调用 run() 方法,run() 方法进入当前调用堆栈而不是新调用堆栈的开头。

          直接调用run()方法的问题举例:

          class TestCallRun2 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.print(i+" ");  
            }  
           }  
           public static void main(String args[]){  
            TestCallRun2 t1=new TestCallRun2();  
            TestCallRun2 t2=new TestCallRun2();  
          
            t1.run();  
            t2.run();  
           }  
          }
          

          输出:

          1 2 3 4 5 1 2 3 4 5

          【讨论】:

            【解决方案8】:

            虽然直接调用run()是合法的,但是会破坏多线程的目的。线程通过拥有自己的调用堆栈独立工作,如果我们不使用start() 方法,那么该语句的执行堆栈将是该语句正在运行的当前堆栈(在大多数情况下为main() 方法)。这将破坏在我们的 main() 方法或换句话说主堆栈运行时同时运行作业的目的。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2014-06-13
              • 2016-05-22
              • 1970-01-01
              • 2013-07-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多