概要:new Thread 并不意味着已经创建了一个线程,只能说明创建一个类的对象实例而已。而真正创建线程的是start()方法,此方法将调用本地方法start0()创建本地线程,而Thread的run()方法其实是作为一个回调函数被JVM创建的线程所调用。
构造方法与线程创建有关吗,它做了什么?
我们还是来看看源码吧,看Thread的构造方法到底做了什么,各构造重载方法都调用了init方法,而这段代码就是init方法的主要内容:
有上述代码可得,构造方法实现的内容无非就是继承父线程的属性,如是否是后台线程,优先级等,并生成一个线程名称。仅此而已,并没有任何与创建线程有关的操作。
线程是何时创建的?
由注释可知,Start方法将创建一个线程(通过调用本地方法start0),然后JVM会利用新创建的本地线程回调Thread对象的run方法。
JVM如何创建线程及回调run方法,可参考这篇文章:Java创建线程的方法
不调用Thread对象的start()方法,而是直接调用run()方法会如何?
那结果就是没有创建线程,而是在原调用线程执行run方法。
示例代码:
public class ThreadRunTest {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(3); //延迟打印
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task Completed");
}
};
Thread t = new Thread(runnable);
t.run();
System.out.println("Main Thread print"); //如果t.run()是另外一个线程执行的话,此字符串将先被输出
}
}
程序输出:
此段代码中,run方法执行的线程仍然是Main主线程。与下述代码基本等价:
public class ThreadRunTest {
public static void main(String[] args) { //begin
try {
TimeUnit.SECONDS.sleep(3); //延迟打印
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task Completed");
//end System.out.println("Main Thread print"); //如果t.run()是另外一个线程的话,此字符串将先被输出 }
}
值得一提的是,Runable并没有多么神秘,它不过是一个很普通的接口,有一个run()方法,里面只是要运行的代码块。仅此而已。它的使用方式就是,把要运行的代码块写到run方法里面去,然后找一个线程去执行这个方法,就这样。