为啥不能直接调用run()方法呢?
Posted
技术标签:
【中文标题】为啥不能直接调用run()方法呢?【英文标题】:Why can't we directly call the run() method?为什么不能直接调用run()方法呢? 【发布时间】:2011-01-28 16:01:16 【问题描述】:如果一个线程的start()方法在内部调用了run()方法,那为什么不在我们的代码中直接调用run()方法呢?这样做会涉及哪些问题?
【问题讨论】:
***.com/questions/262816/… 这是一个非常基本的问题,可以通过非常基本的互联网搜索来回答...@birryree:这是一个非常不同的问题。 没关系,HB。如果它与编程相关并且之前没有被 here 询问过,那么它属于这里。这样,与编程相关的内容的互联网搜索将被定向到此处,而不是那些狡猾的 AskJeeves/ExpertSexChange 网站。 @H.B. - 我链接的问题不同,但答案提供了对start()
和run()
之间差异的相同见解,就像在这个答案中一样:***.com/questions/262816/…
@paxdiablo:猜猜这是一个公平的观点。 @birryree:你再次链接到这个问题,但我明白你的意思,还有其他几个问题也有答案可以回答这个问题。
【参考方案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++)
tryThread.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()
方法或换句话说主堆栈运行时同时运行作业的目的。
【讨论】:
以上是关于为啥不能直接调用run()方法呢?的主要内容,如果未能解决你的问题,请参考以下文章
为什么我们调用 start()方法时会执行 run()方法,为什么 我们不能直接调用 run()方法?
为什么我们调用start()方法时会执行run()方法,为什么我们不能直接调用run()方法?
为什么我们调用start()方法时会执行run()方法,为什么我们不能直接调用run()方法?