多线程

实现多线程的正确姿势

2020-08-11  本文已影响0人  刘一帆315

实现多线程的方法到底有几种?

度娘告诉我们多线程的实现方式

关于多线程的实现方式,互联网上的资源鱼龙混杂,有两种的还有三种四种的,最多的还有六种的。但是正确的答案只可能是三种四种或者六种中的其中个,那么Oracle官方是怎么说的呢?


JDK官方文档

一共有两种实现多线程的方法,一种是实现Runnable接口,一种是继承Thread类。

方法一:实现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方法实现线程");
    }
}

方法二:继承Thread类

/**
 * 描述:     用Thread方式实现线程
 */
public class ThreadStyle extends Thread{

    @Override
    public void run() {
        System.out.println("用Thread类实现线程");
    }

    public static void main(String[] args) {
        new ThreadStyle().start();
    }
}

我们再来看一下源码


Thread类

当我们使用实现Runnable接口方式创建线程时会传入一个target对象,然后判断不为空执行run方法。继承Thread类创建线程时会重写run方法,子类覆盖父类,没有了判断过程。

方法一(实现Runnable接口)更好。
1.Java只支持单根继承,所以实现Runnable接口更加灵活。方法一最终调用target.run(); 方法二run()整个方法都被重写。
2.方法一传入Runnable实例可以重复利用线程,如果使用方法二则会不断的new Thread。
3.run方法中执行的是具体的任务,线程的声明周期是Thread类的事情。这两个事情目的不同,站在代码架构的角度,应该解耦。

我们来看一种特殊的情况,创建线程的时候既实现了Runnable接口又继承了Thread类。

/**
 * 描述:     同时使用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。因为虽然我们实现了Runnable接口,但是重写了run方法,上边Thread类的三行代码被覆盖。最终执行的只有我们重写的run方法。

方法的总结

实现多线程通常我们可以分为两类,Oracle也是这么说的。准确的讲,创建线程只有一种方式那就是构造Thread类,而实现线程的执行单元有两种方式。
       方法一:实现Runnable接口的run方法,并把Runnable实例传给Thread类。
       方法二:重写Thread的run方法(继承Thread类)。

典型的错误观点分析

线程池创建线程也算是一种新建线程的方式

线程池的内部线程工厂也是使用new Thread()的方法创建线程的。

通过Callable和FutureTas看创建线程,也算是一种新建线程的方式。

通过查看类的关系,本质上也是实现Runnable接口的。

无返回值是实现runnable接口,有返回值是实现callable接口,所有callable是新的实现线程的方式。

和上边一样,并没有创新。

定时器

和线程池的观点并没有不同。

匿名内部类

Lambda表达式

只是表象不同,本质都是利用两种方法创建线程。多线程的实现方式在打吗中写法千变万化,但其本质万变不离其宗。

上一篇 下一篇

猜你喜欢

热点阅读