Thread start()和Runnable run()之间有什么区别
假设我们有这两个Runnables:
class R1 implements Runnable { public void run() { … } … } class R2 implements Runnable { public void run() { … } … }
那么有什么区别呢:
public static void main() { R1 r1 = new R1(); R2 r2 = new R2(); r1.run(); r2.run(); }
和这个:
public static void main() { R1 r1 = new R1(); R2 r2 = new R2(); Thread t1 = new Thread(r1); Thread t2 = new Thread(r2); t1.start(); t2.start(); }
第一个例子:没有多个线程。 两者都在单个(现有)线程中执行。 没有线程创build。
R1 r1 = new R1(); R2 r2 = new R2();
r1
和r2
只是实现Runnable
接口的类的两个不同对象,因此实现了run()
方法。 当你调用r1.run()
你正在当前线程中执行它。
第二个例子:两个独立的线程。
Thread t1 = new Thread(r1); Thread t2 = new Thread(r2);
t1
和t2
是Thread
类的对象。 当你调用t1.start()
,它会启动一个新线程,并在内部调用r1
的run()
方法在新线程中执行它。
如果你直接调用run()
,它就像调用其他方法一样在调用线程上执行。 Thread.start()
是实际创build一个新的线程所需要的,这样runnable的run
方法就可以并行执行。
不同的是Thread.start()启动一个线程,而Runnable.run()只是调用一个方法。
主要区别在于,当程序调用start()
方法时,会创build一个新的Thread ,并在new Thread中执行run()方法中的代码,而如果直接调用run()
方法,则不会创build新的Thread ,并且run在当前线程 。
Java线程的启动与运行之间的另一个区别是,您不能在线程对象上调用两次start()方法 。 一旦启动,第二次调用start()将在Java中抛出IllegalStateException,而您可以调用run()方法两次。
其实Thread.start()
创build一个新的线程,并有自己的执行scheme。
Thread.start()
asynchronous调用run()
方法,将新线程的状态更改为Runnable。
但是Thread.run()
不会创build任何新的线程。 而是在当前正在运行的线程中同步执行run方法。
如果你正在使用Thread.run()
那么你根本就没有使用multithreading的function。
调用run()
在调用线程上执行,就像任何其他方法调用一样。 而Thread.start()
创build一个新的线程。 调用run()
是一个编程错误。
如果你在main方法中run()
,main方法的线程将调用run
方法而不是你需要运行的线程。
start()
方法创build新线程,并且run()
方法必须完成
Thread.start()
代码向调度程序注册Thread,调度程序调用run()
方法。 此外, Thread
是类而Runnable
是一个接口。
成员们提出的观点都是对的,所以我只想补充一些东西。 事情是,JAVA不支持多inheritance。 但是,如果你想从另一个类A派生出一个类B,但是你只能从一个类派生。 现在的问题是如何从类A和线程“派生”。 因此您可以使用Runnable接口。
public class ThreadTest{ public void method(){ Thread myThread = new Thread(new B()); myThread.start; } } public class B extends A implements Runnable{...
这些答案中的大部分都错过了大局,就Java语言而言, t.start()
和r.run()
之间没有任何其他两种方法之间的区别。
他们都只是方法。 他们都在调用它们的线程中运行。 他们都做他们所做的任何事情,然后他们都回到他们的调用者。
最大的区别是t.start()
大部分代码是本地代码,而在大多数情况下, r.run()
的代码将是纯Java。 但是这并没有太大的区别。 代码是代码。 原生代码很难find,find时难以理解,但它仍然只是告诉计算机做什么的代码。
那么, t.start()
做什么的?
它创build一个新的本地线程,它安排该线程调用t.run()
,然后告诉操作系统让新线程运行。 然后它返回。
r.run()
做什么的?
有趣的是,问这个问题的人就是写这个问题的人。 r.run()
做你所做的任何事情 (也就是写它的开发者)devise它。
t.start()
是当你想要一个新的线程时,库提供给你的代码调用的方法。
r.run()
是您提供的库 在新线程中调用的方法。
如果直接调用run()
方法,则不会使用multithreadingfunction,因为run()
方法是作为调用者线程的一部分执行的。
如果在Thread上调用start()
方法,Java虚拟机将调用run()方法,并且两个线程将同时运行 – 当前线程(在您的示例中为main()
)和其他线程(在您的示例中为Runnable r1
)。
看一下Thread类中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执行这个本地方法。
在第一种情况下,你只是调用r1和r2对象的run()函数。
在第二种情况下,您实际上正在创build2个新线程! ;)start()会在同一个点调用run()!
Thread类中的单独start()和run()方法提供了两种创build线程化程序的方法。 start()方法启动新线程的执行并调用run()方法。 start()方法立即返回,新线程通常继续,直到run()方法返回。
Thread类的run()方法什么都不做,所以子类应该用第二个线程中要执行的代码覆盖方法。 如果使用Runnable参数实例化一个线程,则线程的run()方法改为执行新线程中的Runnable对象的run()方法。
根据线程化程序的性质,直接调用Thread run()方法可以提供与通过start()方法调用相同的输出,但在后一种情况下,代码实际上是在新线程中执行的。
假设你是一个名为Thread的酒店的经理。 所以基本上,t1.run()所做的就是让你必须自己完成所有的任务,而另一个线程助手则坐在空闲的地方。 但是如果你使用t1.start(),你的一个助手被分配了一些任务,然后他/她开始执行这个任务,而你做这个工作就是pipe理助手。
来源: 编程访谈:操作系统中的线程(Java)第2部分multithreading