• 先看一下API文档:

  • 调用start()方法的时候为什么会产生两个线程呢?

  • API说结果会有两个线程同时并发运行,其实这样:在运行run的过程中产生了一个线程,启动start()的方法又是一个线程,例如以下代码的这个线程是main线程

      public static void main(String[] args) {
         Thread t = new Thread("READ-Thread"){
             @Override
              public void run() {
                 // 获取“当前线程”的名字
                 println(Thread.currentThread().getName()); // READ-Thread线程
                 readFromDataBase();
              }
         };
         t.start(); // main线程
    }
    
     private static void println(String message) {
        System.out.println(message);
     }
    
  • 一个线程不能调用start()方法多次,否则就会报错

      public static void main(String[] args) {
          Thread t = new Thread("READ-Thread"){
              @Override
              public void run() {
                  System.out.println("我是READ-Thread线程");
              }
          };
    
          t.start(); 
          t.start();
        }
    

  • 我们为什么重写了他的run()方法要去调用start()方法去执行呢?如果调用run()方法可以吗?

    public static void main(String[] args) {
        Thread t = new Thread("READ-Thread"){
            @Override
            public void run() {
                println(Thread.currentThread().getName()); // main
                readFromDataBase();
            }
        };

        t.run();
   }

   private static void println(String message) {
        System.out.println(message);
   }
  • 结果输出的线程为main,并没有去启动线程"READ-Thread",也就是说再线程生命周期当中New了但没有调用start()方法就不会存在另外一个线程。
  • 这么做的好处是什么?

  • 首先 Thread 是实现了 Runnable 接口的 现在我们先不管它,先来看一下start()方法的源代码:

  • 那他是做什么的呢?

    • 对于开发者来说,可能写程序的过程中会遇到一些问题:
      • 程序的算法可能已经定了,其中有一些逻辑可能是多变的,那我就想把它抽象出来,让子类去实现。
      • 比如输出一个message在中间了能要加"*"号,或者其他的符号,那先把他定下来,针对不同的情况作出不同的实现方式
    public final void print(String message) {
        System.out.println("################");
        wrapPrint(message);
        System.out.println("################");
    }

    protected void wrapPrint(String message) {

    }

    public static void main(String[] args) {
        TemplateMethod t1 = new TemplateMethod(){
            @Override
            protected void wrapPrint(String message) {
                System.out.println("*"+message+"*");
            }
        };
        t1.print("Hello Thread");

        TemplateMethod t2 = new TemplateMethod(){
            @Override
            protected void wrapPrint(String message) {
                System.out.println("+"+message+"+");
            }
        };

        t2.print("Hello Thread");
    }

    /*
        注意:
             wrapPrint可以写成一个空的实现,也可以写成抽象方法,
             start方法里面没有写成抽象的,那我也不写成抽象的,
             在真正的模板方法里面要写成抽象类,抽象方法,这里不需要。
     */
  • 这就是start()方法的巧妙之处,也就是说start()方法不知道你的业务逻辑到底是什么,主要提供了一个启动线程的方法,那它就抽象出一个Runnable接口(Thread默认实现了),接口里面有个run()方法, run()方法实不实现都可以,实现了之后就写自己的逻辑代码,就像上面的例子一样。

  • 疑惑:重写的是run()方法为何要调用start()方法呢?

  • 答案:其实他是巧妙的用了模板方法的技巧

results matching ""

    No results matching ""