Java多进程的第一篇~ 关于线程创建的方法与底层原理😇

Java多并发 -- 线程创建

实现多线程的方法

  • 实现多线程的官方正确方法:2种

    • 方法一:实现Runnable接口

      // 用Runnable方式创建线程
      public class RunnableStyle implements Runnable{
        public static void main(String[] args){
          Thread thread = new Thread(new RunnableStyle());
          thread.start();
        }
        @Override
        public void run() {
          System.out.println("用Runnable方法实现线程");
        }
      }
      // 打印输出 用Runnable方法实现线程
      
    • 方法二: 继承Thread类

      // 用Thread方式创建线程
      public class ThreadStyle extends Thread{
        public static void main(String[] args){
          new ThreadStyle().start();
        }
        @Override
        public void run() {
          System.out.println("用Thread类实现线程");
        }
      }
      // 打印输出 用Thread类实现线程
      
  • 两种方法的对比

    • 方法1(实现Runnable接口)更好
    • 解耦
    • 性能消耗更低
    • 如果已经继承,限制了可扩展性
  • 两种方法的本质对比(看源码)

    • 方法一:最终调用target.run()
    • 方法二:run()整个都被重写
  • 同时使用两种方法会怎么样?

    /**
     * 描述:     同时使用Runnable和Thread两种实现线程的方式
     */
    public class BothRunnableThread {
        public static void main(String[] args) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("我来自Runnable");
                }
            }) {
                @Override
                public void run() {
                    System.out.println("我来自Thread");
                }
            }.start();
        }
    }
    // 打印输出 我来自Thread
    
  • 准确的来说,创建线程只有一种方式就是构造Thread类,而实现线程的单元创建有两种方法:

    • 方法一:实现Runnable接口的run方法,并把Runnable实例传给Thread类
    • 方法二:重写Thread类的run方法(继承Thread类)
  • 典型错误观点

    • 线程池创建线程也算是一种新建线程的方式
    • 通过 **Callable ** 和 FutureTask 来创建线程
    • 无返回值是实现runnable接口,**有返回值 **是实现Callable接口,所以callable是新的实现线程的方式
    • 定时器(底层也是自动创建)
    • 匿名内部类(语法层面)
    • Lambda表达式(语法层面)
  • 本质万变不离其宗

  • 常见面试问题

    • 有多少种实现线程的方法?5点思路
      • 从不同的角度看,会有不同的答案
      • 典型答案是两种
      • 我们看原理,两种本质都是一样的
      • 具体展开说其他方式
      • 结论
    • 实现Runnable接口和继承Thread类那种方式更好
      • 从代码架构角度(解耦合)
      • 新建线程的损耗(新建类消耗大)
      • Java不支持双继承(继承会麻烦)