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();
}
203482 次浏览

第一个例子:没有多线程。两者都在单个(现有)线程中执行。没有线程创建。

R1 r1 = new R1();
R2 r2 = new R2();

r1r2只是实现了Runnable接口的两个不同的类对象,因此实现了run()方法。当你调用r1.run()时,你是在当前线程中执行它。

第二个例子:两个独立的线程。

Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);

t1t2是类Thread的对象。当你调用t1.start()时,它会启动一个新线程,并在内部调用r1run()方法来在那个新线程中执行它。

如果直接调用run(),它将在调用线程上执行,就像任何其他方法调用一样。需要Thread.start()来实际创建一个新线程,以便并行执行可运行对象的run方法。

在第一种情况下,你只是调用r1r2对象的run()方法。

在第二种情况下,您实际上创建了2个新线程!

start()将在某个时刻调用run() !

Thread.start()代码向调度器注册线程,调度器调用run()方法。另外,Thread是类,而Runnable是接口。

实际上Thread.start()创建了一个新线程,并有自己的执行场景。

Thread.start()异步调用run()方法,它将new Thread的状态更改为Runnable。

但是Thread.run()不会创建任何新的线程。相反,它在当前运行的线程中同步执行run方法。

如果你正在使用Thread.run(),那么你根本就没有使用多线程的特性。

如果你在main方法中执行run(), main方法的线程将调用run方法,而不是你需要运行的线程。

start()方法创建新线程,并且必须为其执行run()方法

区别在于Thread.start()启动了一个调用run()方法的线程,而Runnable.run()只调用当前线程上的run()方法。

invoke run()在调用线程上执行,就像任何其他方法调用一样。而Thread.start()创建一个新线程。 调用run()是一个编程错误。< / p >

成员们提出的观点都是对的所以我想补充一点。问题是JAVA不支持多继承。但是如果你想从另一个类a中派生一个类B,但你只能从一个类中派生。现在的问题是如何从这两个类中“派生”:A和Thread。因此,您可以使用可运行接口。

public class ThreadTest{
public void method(){
Thread myThread = new Thread(new B());
myThread.start;
}
}


public class B extends A implements Runnable{...

Thread类中单独的start()和run()方法提供了两种创建线程程序的方法。start()方法启动新线程的执行,并调用run()方法。start()方法立即返回,新线程通常会继续,直到run()方法返回。

Thread类的run()方法什么也不做,所以子类应该用在第二个线程中执行的代码重写该方法。如果一个线程是用Runnable参数实例化的,线程的run()方法会在新线程中执行Runnable对象的run()方法。

根据线程程序的性质,直接调用Thread run()方法可以得到与通过start()方法调用相同的输出,但在后一种情况下,代码实际上是在一个新线程中执行的。

t.start()是标准库为你的代码提供的方法,当你想要一个新线程时调用它。

r.run()图书馆调用新线程提供的方法。


这些答案大多数都忽略了大局,即就Java语言而言,t.start()r.run()之间的差异并不比其他任何两个方法之间的差异更大。

它们都是方法。它们都运行在调用它们的线程中。它们都做它们被编码要做的事情,然后它们都返回给它们的调用者,仍然在同一个线程中。

最大的区别是t.start()的大部分代码是本地的代码,而在大多数情况下,r.run()的代码将是纯Java。但这并没有太大的区别。代码就是代码。原生代码更难找到,找到后也更难理解,但它仍然只是告诉计算机该做什么的代码。

那么,t.start()是做什么的呢?

它创建了一个新的本机线程,它安排该线程调用t.run(),然后它告诉操作系统让新线程运行。然后它又回来了。

r.run()是做什么的?

有趣的是,问这个问题的人是写的r.run()做任何(即编写它的开发人员)设计它要做的事情。

区别在于,当程序调用start()方法时,会创建一个线程,而run()方法中的代码将在新线程中执行:而如果直接调用run()方法,则不会创建新线程,run()方法中的代码将直接在当前线程中执行。

Java线程中start()run()的另一个区别是你不能调用start()两次。一旦启动,第二次start()调用将在Java中抛出IllegalStateException,而你可以多次调用run()方法,因为它只是一个普通的方法。

如果直接调用run()方法,则没有使用多线程特性,因为run()方法是作为调用者线程的一部分执行的。

如果你在线程上调用start()方法,Java虚拟机将调用run()方法,两个线程将并发运行——当前线程(在你的例子中是main())和其他线程(在你的例子中是可运行的r1)。

查看线程类 ?中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执行这个本机方法。

Start()方法调用Thread扩展类和Runnable实现接口的运行重写方法。

但是通过调用run()它会搜索run方法,但如果类实现了Runnable接口,那么它会调用run()重写Runnable方法。

例:

public class Main1
{
A a=new A();
B b=new B();
a.run();//This call run() of Thread because run() of Thread only call when class
//implements with Runnable not when class extends Thread.
b.run();//This not run anything because no run method found in class B but it
//didn't show any error.


a.start();//this call run() of Thread
b.start();//this call run() of Thread
}


class A implements Runnable{
@Override
public void run() {
System.out.println("A ");
}
}


class B extends Thread {


@Override
public void run() {
System.out.println("B ");
}
}