Thread线程start方法的深入解析:模板设计模式的使用

大部分面试时面试官会问,为什么开始一个线程时调用start方法而不是run方法呢?这里主要涉及到Thread里用到了模板设计模式。

  1. public class test {
  2. public final void print(){
  3. System.out.println("##################");
  4. messgae();
  5. System.out.println("##################");
  6. }
  7. public void messgae(){}
  8. public static void main (String arg[]) throws Exception{
  9. test t=new test(){
  10. @Override
  11. public void messgae(){
  12. System.out.println("我是执行体");
  13. }
  14. };
  15. t.print();
  16. }
  17. }

类似这样的就是模板设计模式,程序结构由父类控制,执行体由子类来实现。上面的print方法对应于Thread类的start方法,而messgae对应于
Thread类的run方法,接下来我们查看Thread类的start方法和run方法

  1. public synchronized void start() {
  2. if (threadStatus != 0)
  3. throw new IllegalThreadStateException();
  4. group.add(this);
  5. boolean started = false;
  6. try {
  7. start0();
  8. started = true;
  9. } finally {
  10. try {
  11. if (!started) {
  12. group.threadStartFailed(this);
  13. }
  14. } catch (Throwable ignore) {
  15. /* do nothing. If start0 threw a Throwable then
  16. it will be passed up the call stack */
  17. }
  18. }
  19. }

start方法代码很简单,但是核心的方法是这个 start0();但是这个start0是一个本地方法

  1. private native void start0();

但是run方法什么时候被调用了呢,这里我们完全看不出,于是JDK文档的start方法上面有一句话说:

  1. Causes this thread to begin execution; the Java Virtual Machine calls the runcode> method of this thread.

也就是说在线程开始时,jVM会调用这个run,也就是本地方法start0会调用这个run方法,于是我们再看看run方法的

  1. @Override
  2. public void run() {
  3. if (target != null) {
  4. target.run();
  5. }
  6. }

我们发现这个run方法有个target,我们再找到这个target,原来target是

  1. /* What will be run. */
  2. private Runnable target;

所以Thread再这里判断是否有Runnable实现类,如果没有就是空的实现,

2.总结创建线程方式
如果你是继承Thread来创建线程,那么你可以直接重载run方法
如果你是用实现Runnable的接口,你只要实现Runnable接口的run方法,然后传入Thread来创建线程,然后Thread的run方法会调用Runnable接口的run方法。
总结:所以无论怎么样,我们都要是用Thread类来创建线程的,也就是说我们创建线程只有Thread类,而创建执行单元有多种方式,比如继承Thread类重载run方法或者实现Runnable接口的run方法。