假设我们有两个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();
}
答案 0 :(得分:290)
第一个例子:没有多个线程。两者都在单个(现有)线程中执行。没有线程创建。
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()
时,它会启动一个新线程,并在内部调用run()
r1
方法在该新线程中执行它。
答案 1 :(得分:88)
如果你只是直接调用run()
,它就会在调用线程上执行,就像任何其他方法调用一样。实际创建一个新线程需要Thread.start()
,以便并行执行runnable的run
方法。
答案 2 :(得分:62)
区别在于Thread.start()
启动调用run()
方法的线程,而Runnable.run()
只调用当前线程上的run()
方法。
答案 3 :(得分:30)
差异是当程序调用{{1}}方法时,会创建新线程,并在中执行start()
内的代码新的线程,如果直接调用run()
方法将不会创建新的线程,run()
内的代码将直接在当前线程中执行。
Java线程中run()
和start()
之间的另一个差异是无法两次调用run()
。一旦开始,第二个start()
调用会在start()
中抛出IllegalStateException
,而您可以多次调用run()
方法,因为它只是一个普通方法。< / p>
答案 4 :(得分:22)
实际上Thread.start()
创建了一个新线程并拥有自己的执行场景。
Thread.start()
异步调用run()
方法,这会将新Thread的状态更改为Runnable。
但是Thread.run()
不会创建任何新线程。相反,它会同步在当前运行的线程中执行run方法。
如果您使用的是Thread.run()
,那么您根本就没有使用多线程的功能。
答案 5 :(得分:8)
invoke run()
正在调用线程上执行,就像任何其他方法调用一样。而Thread.start()
创建一个新线程。
调用run()
是一个程序化错误。
答案 6 :(得分:6)
如果在main方法中执行run()
,main方法的线程将调用run
方法而不是运行所需的线程。
start()
方法创建新线程并且必须为其执行run()
方法
答案 7 :(得分:5)
Thread.start()
代码使用调度程序注册Thread,调度程序调用{{1}}方法。此外,run()
是类,而Thread
是接口。
答案 8 :(得分:4)
大多数答案都错过了大局,就Java语言而言,t.start()
和r.run()
之间的区别与其他两种方法之间没有区别。
他们都是方法。它们都在调用它们的线程中运行 。他们都做了他们编码做的任何事情,然后他们都在同一个线程中返回给他们的来电者。
最大的区别是t.start()
的大部分代码都是 native 代码,而在大多数情况下,r.run()
的代码将是纯Java。但这并没有多大区别。代码是代码。原生代码很难找到,当你找到它时更难理解,但它仍然只是告诉计算机做什么的代码。
那么,t.start()
做了什么?
它创建一个新的本机线程,它安排该线程调用t.run()
,然后它告诉操作系统让新线程运行。然后它返回。
r.run()
做了什么?
有趣的是,提出此问题的人是编写的人。 r.run()
会为你(即编写它的开发人员)做任何事情而设计它。
t.start()
是库为您的代码在需要新线程时调用的方法。
r.run()
是您为库提供的方法,用于在新线程中调用。
答案 9 :(得分:3)
成员们提出的要点是正确的,所以我只想添加一些内容。问题是JAVA不支持多继承。但是,如果你想从另一个A类派生一个B类,但是你只能从一个Class派生出来。现在的问题是如何&#34;派生&#34;来自两个类:A和Thread。因此,您可以使用Runnable接口。
public class ThreadTest{
public void method(){
Thread myThread = new Thread(new B());
myThread.start;
}
}
public class B extends A implements Runnable{...
答案 10 :(得分:2)
如果直接调用run()
方法,则不使用多线程功能,因为run()
方法作为调用方线程的一部分执行。
如果在Thread上调用start()
方法,Java虚拟机将调用run()方法,并且两个线程将同时运行 - 当前线程(在您的示例中为main()
)和其他线程(Runnable {在你的例子中{1}}。
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()
方法。 JVM执行此本机方法。
答案 11 :(得分:1)
在第一种情况下,您只是调用run()
和r1
对象的r2
方法。
在第二种情况下,你实际上是在创建2个新线程!
start()
会在某个时候致电run()
!
答案 12 :(得分:0)
运行方法: -是最初在Runnable接口中创建的抽象方法,并在Thread类以及Thread子类(因为Thread在其源代码中实现Runnable)和任何其他Runnable接口的实现类中被覆盖。 -它用于将要执行的任务加载到线程(可运行对象)中,因此您可以重写它以编写该任务。
启动方法: -在Thread类中定义。 在Thread对象上调用start方法时 1-;它调用称为start0()的内部本地(非Java)方法;方法。
start0();方法: 负责低处理(此时为线程创建堆栈并在处理器队列中分配线程),此时我们的线程处于Ready / Runnable状态。
2-在线程调度程序确定某个线程进入处理器内核时,会在Runnable对象上调用运行方法(线程优先级以及OS调度算法)(是否当前的Runnable线程对象或传递给线程构造函数的Runnable对象),这里的线程进入运行状态并开始执行其任务(运行方法)
答案 13 :(得分:-1)
Start()方法调用Thread扩展类的run override方法和Runnable实现接口。
但是通过调用run()它会搜索run方法但是如果类实现了Runnable接口,那么它调用runnable的run()覆盖方法。
例如:
`
//Loop and Draw Path Route between the Points on MAP
for (var i = 0; i < lat_lng.length; i++) {
if ((i + 1) < lat_lng.length) {
var src = lat_lng[i];
var des = lat_lng[i + 1];
service.route({
origin: src,
destination: des,
travelMode: google.maps.DirectionsTravelMode.DRIVING
}, function(result, status) {
if (status == google.maps.DirectionsStatus.OK) {
//Set the Path Stroke Color
var poly = new google.maps.Polyline({
map: map,
strokeColor: '#4986E7'
});
//Intialize the Path Array
var path = new google.maps.MVCArray();
for (var i = 0, len = result.routes[0].overview_path.length; i < len; i++) {
path.push(result.routes[0].overview_path[i]);
}
poly.setPath(path);
}
});
}
}
`
答案 14 :(得分:-2)
Thread类中的单独start()和run()方法提供了两种创建线程程序的方法。 start()方法开始执行新线程并调用run()方法。 start()方法立即返回,新线程通常会继续,直到run()方法返回。
Thread类&#39; run()方法什么都不做,所以子类应该用代码覆盖方法,以便在第二个线程中执行。如果使用Runnable参数实例化Thread,则线程的run()方法会在新线程中执行Runnable对象的run()方法。
根据线程程序的性质,直接调用Thread run()方法可以提供与通过start()方法调用相同的输出,但在后一种情况下,代码实际上是在新线程中执行的。 / p>