实现多线程的正确姿势

网上和书籍的各种说法:鱼龙混杂

在这里插入图片描述

正确的说法

在这里插入图片描述

方法一:实现Runnable接口

package threadcoreknowledge.createthreads;

/**
 * 描述:     用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

package threadcoreknowledge.createthreads;

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

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

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

实现Runnable接口更好一些原因如下:

run方法源码解析:

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

    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }


实现Runnable接口最终会调用 target.run() 但是继承Thread类的run方法整个都被重写。

继承Thread有如下缺点:

1、从代码的架构考虑的话:run方法里面的内容(对应我们具体执行的任务),它应该和我们和线程的创建、运行等机制也就是Thread类是解耦的,所以不应该把这两个事情混为一谈,从解耦的角度是有缺点的。
2、如果说继承了Thread类,用这种方法的话,每次如果我们需要新建一个任务,只能去新建一个独立的线程,而新建一个独立的线程这样的损耗是比较大的,需要创建、执行、销毁等,而如果使用Runnable接口的话,后面就会使用线程池等一些工具,就可以大大减小创建线程带来的损耗,从资源节约的角度上也是优缺点的。
3、Java不支持多继承,如果继承了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();
    }
}

运行之后:
在这里插入图片描述
分析:这是因为run方法被重写了,这是target.run就不会执行了。

在这里插入图片描述

常见错误观点:

1、“线程池创建线程也是一种新建线程的方式”
虽然利用线程成可以创建线程,但是这只是表象,不属于创建线程的本质。通过深入Executors的源码可以看到,在线程池的内部,也是新建了Thread类来执行这些任务的。
在这里插入图片描述
2、“通过Callable和FutureTAsk创建线程,也算是一种新建线程的方式。”
3、“无返回值是实现runnable接口,有返回值是实现callable接口,所以callable是新的实现线程的方式”
4、“匿名内部类”
5、“Lambda表达式”

综上所述,这些错误观点的本质都是离不开Runnable接口和Thread类的。都属于表明现象。多线程的实现方式,在代码中写法千变万化,但本质不变。

常见面试题。

在这里插入图片描述

在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值