史上最简单的多线程核心知识

多线程核心知识之开启线程的多种姿势

说到开启线程的姿势,你的脑海中闪过的是几种方式?是两种?还是三种?还是四种五种六种?我想机智的你肯定第一时间会先去百度看看,毕竟是互联网时代嘛~那我们先一起百度去看看网上大家说的都是几种呢?
在这里插入图片描述

我们可以看到百度上大多数人说的都是为三种方式,第一种是继承Thread类,第二种是实现Runnable接口,第三种是实现Callable接口。还有的人说线程池也可以开启线程,我不禁怀疑,到底谁是对的呢。。。
在这里插入图片描述

既然大家都是众说纷纭,那我们还是相信官方的说方法,一起去ORCLE官网去看看是怎么说的(ORCLE THREAD OBJECTS),下面我直接选取了官网说两种方式截图贴在了下面,大家一起来看看

在这里插入图片描述
仔细一看,竟然是全英文的,内心不禁卧槽了一句,那让我来翻译一下ORCLE主要说的是什么

每一个线程都是Thread实例,并发应用中有两种不同的线程创建策略
1.直接控制线程的创建与管理,每个应用程序需要执行异步任务的时候就为其创建一个线程
2.将线程的管理从应用程序中抽象出来作为执行器,应用程序将任务传递给执行器,由执行器负责执行

这段话简单翻译过来的意思是要么你创建一个线程,要么你创建一个执行器,然后再将任务传递给执行器,显而易见,官网给出的答案就是2种,分别为继承Thread类和实现Runnable接口,那咱们废话不多说,直接开始撸代码。

首先咱们开始演示的为继承Thread类


package com.zhou.threadknowledge;

/**
 * FileName: createThreadByExtends
 *
 * @author mozzie
 * @date 2020/4/14 11:50
 * description: 重写Thread类中的run方法
 */

public class CreateThreadByExtends extends Thread {

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(i);
        }
    }

    public static void main(String[] args) {
        CreateThreadByExtends thread = new CreateThreadByExtends();
        thread.run();
        thread.start();
    }
}

接着咱们开始演示实现Runnable接口

package com.zhou.threadknowledge;

/**
 * FileName: CreateThreadByImplements
 *
 * @author zhou
 * @date 2020/4/14 11:54
 * description: 实现Runnable接口
 */

public class CreateThreadByImplements implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(i);
        }
    }

    public static void main(String[] args) {
        CreateThreadByImplements runnableThread = new CreateThreadByImplements();
        Thread thread = new Thread(runnableThread);
        thread.start();
    }
}

以上两种就是绝对官方创建线程的方式,可是小伙伴们再仔细看看却也不难发现,说是两种,其实本质上是只有一种方式,为何这么说,我们不妨走进去继续看看源码是怎么写的

/**
 * If this thread was constructed using a separate
 * <code>Runnable</code> run object, then that
 * <code>Runnable</code> object's <code>run</code> method is called;
 * otherwise, this method does nothing and returns.
 * <p>
 * Subclasses of <code>Thread</code> should override this method.
 *
 * @see     #start()
 * @see     #stop()
 * @see     #Thread(ThreadGroup, Runnable, String)
 */
@Override
public void run() {
    if (target != null) {
        target.run();
    }
}

我截取了Thread类中的run方法,发现方法一即继承Thread类然后重写run方法,方法二中实现runnable接口并传入Thread类,其实本质并没有任何区别,最终都是调用了Thread类中的start方法,这两个方法的主要区别即是run方法的来源不同而已。

我们再接着去看例如线程池、定时器,也会发现万变不离其宗,无非是上面两种方法的变种而已

由此可知,本质上创建线程只有一种方式,就是新建Thread类,但是类里面的run方法有两种的实现方法,方法一为继承Thread类重写run方法,方法二为实现Runnable接口中的run方法,然后再把该实例传给Thread类,除此之外,线程池,定时器,甚至Lamabda表达式都是通过这两种方式,本质都逃离不了这两个方法。

本问阐释了多线程中如何用正确的姿势去创建多线程,但是创建多线程中继承Thread类与实现Runnable接口我到底又应该选择哪种呢?这两个到底有何区别呢?我既然已经创建了多线程那么又如何去开启多线程呢?我会在后续文章中进行进一步的阐释,请大家持续关注哟~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值