您什么时候会调用 Javathread.run()
而不是thread.start()
?
14 回答
您可能希望在严格关注功能而非并发性的特定单元测试中调用 run()。
绝不。直接调用 run() 只是同步执行代码(在同一个线程中),就像普通的方法调用一样。
问:线程的 start() 和 run() 方法有什么区别?
A: Thread 类中单独的 start() 和 run() 方法提供了两种创建线程程序的方法。start() 方法开始执行新线程并调用 run() 方法。start() 方法立即返回,并且新线程通常会继续,直到 run() 方法返回。
Thread 类的 run() 方法什么都不做,因此子类应该用代码覆盖该方法以在第二个线程中执行。如果使用 Runnable 参数实例化 Thread,则该线程的 run() 方法将在新线程中执行 Runnable 对象的 run() 方法。
根据线程程序的性质,直接调用 Thread run() 方法可以提供与通过 start() 方法调用相同的输出,但在后一种情况下,代码实际上是在新线程中执行的。
执行thread.run()
不会创建一个新Thread
的代码在其中执行。它只是在调用代码的当前线程中执行thread.run()
代码。
执行thread.start()
创建一个新的操作系统级线程,其中run()
调用该方法。
在本质上:
单线程编程→直接调用
run()
方法
多线程编程→调用
start()
方法
此外,正如其他人所提到的,“测试”似乎是您可以run()
直接从代码中调用的唯一可取的情况。
这已经被提到过,但要明确一点:创建一个新的 Thread 对象只是为了调用它的 run() 方法是不必要的昂贵并且应该是一个主要的危险信号。创建一个 Runnable impl 并(a)直接调用它的run() 方法(如果这是所需的行为)或者 (b) 使用该 Runnable 构造一个新线程并启动线程,这将是一个更好、更解耦的设计。
更好的是,为了进一步解耦,请查看Executor
JDK 5 和更新版本中的接口和框架。简而言之,这允许您将任务执行(Runnable 实例)与其执行方式(Executor 实现,它可能在当前线程中执行 Runnable,在新线程中,使用池中的现有线程,等等)。
调用thread.start()
,它会依次调用thread.run()
。想不出你想绕过thread.start()
直接去的情况thread.run()
Thread 类中的separatestart()
和run()
方法提供了两种创建线程程序的方法。该start()
方法开始执行新线程并调用该run()
方法。该start()
方法立即返回,并且新线程通常会继续,直到该run()
方法返回。
Thread 类的run()
方法什么都不做,所以子类应该用代码覆盖该方法以在第二个线程中执行。如果使用 Runnable 参数实例化 Thread,则该线程的run()
方法将run()
改为在新线程中执行 Runnable 对象的方法。
根据线程程序的性质,run()
直接调用 Thread 方法可以提供与通过方法调用相同的输出start()
,但在后一种情况下,代码实际上是在新线程中执行的。
如果问题是 - “为什么调用线程启动方法而不是直接调用运行方法”,那么我已经用下面的示例代码回答了。希望澄清。在下面的示例中:
/*
By calling t1.start(),
we are getting the main calling thread returned immediately
after the t1.start() called and is ready to proceed for other
operations.And the thread t1 starts executing the run method of the object r.
Hence the the output will be:
I am the main thread , i created thread t1 and had it execute run method, which is currently looping from 0 to 1000000
I am done executing run method of testThread
*/
/* If we call t1.run() instead of t1.start(), (just replace t1.start() with t1.run() in the code for testing)
its like a regular method call and the main thread will not return until the run method completes,
hence the output will be:
I am done executing run method of testThread
I am the main thread , i created thread t1 and had it execute run method, which is currently looping for i to 1000000
*/
class testThread implements Runnable{
public void run()
{
for(int i=0;i<1000000;i++){} //a simple delay block to clarify.
System.out.println("I am done executing run method of testThread");
}
}
public class mainClass{
public static void main(String [] args)
{
testThread r = new testThread();
Thread t1 = new Thread(r);
t1.start(); /* Question is: can we call instead t1.run() */
System.out.println("I am the main thread , i created thread t1 and had it execute run method, which is currently looping for i to 1000000");
}
}
当您希望它同步运行时。调用 run 方法实际上不会为您提供多线程。start 方法创建一个调用 run 方法的新线程。
如果您想像执行任何其他方法一样执行 run() 的内容。当然,不要启动线程。
假设您知道启动和运行方法的用法,即同步与异步;run 方法可以用来测试功能。
另外,在某些情况下,可以在两个不同的地方使用同一个线程类,通过调用两个不同的对象来调用一个 run 方法和另一个 start 方法,从而满足同步和异步功能要求。
至少在 JVM 1.6 中,有一些检查和 run 被本地调用:
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();
只是对上述精彩评论的一个注释:有时你会编写一个多线程代码,它使用“start”方法来运行不同的线程。如果您使用“运行”(而不是“开始”)进行调试,您会发现它会更容易,因为它使代码同步运行并更容易调试。
public class TestClass implements Runnable {
public static void main(String[] args) {
TestClass tc = new TestClass();
Thread t1 = new Thread(tc);
System.out.println("Before Starting Thread " + Thread.currentThread().hashCode());
t1.start();
System.out.println("After Starting Thread " + Thread.currentThread().hashCode());
}
@Override
public void run() {
System.out.println("TestClass Run method is Running with thread " + Thread.currentThread().hashCode());
}
}