点击上方 好好学java ,选择 星标 公众号

重磅资讯、干货,第一时间送达
今日推荐:终于放弃了单调的swagger-ui了,选择了这款神器—knife4j个人原创100W+访问量博客:点击前往,查看更多

多线程在工作中多多少少会用到,启动多线程调用的是 start() 方法,而不是 run() 方法,这是为什么呢?

在探讨这个问题之前,先来了解(复习)一些多线程的基础知识~

线程的状态

Java 中,定义了 6 种线程状态,在 Thread 类可以找到:

// 为了节约空间,我删除了注释
public enum State {NEW,//初始状态RUNNABLE,//运行状态BLOCKED,// 阻塞状态WAITING,//等待状态TIMED_WAITING,//超时等待状态TERMINATED;//终止状态}

这 6 种状态之间的关联,可以看下面这张图:

图片来源网络

附上我历时三个月总结的 Java面试思维导图,拿去不谢!

下载方式

1. 首先扫描下方二维码

2. 后台回复「思维导图」即可获取

这张图描述的还是非常详细的,结合这张图,来说说这几种状态分别代表着什么意思:

  • 1、NEW 表示线程创建成功,但没有运行,在 new Thread 之后,没有 start 之前,线程都处于 NEW 状态;

  • 2、RUNNABLE 表示线程正在运行中,当我们运行 strat 方法,子线程被创建成功之后,子线程的状态变成 RUNNABLE;

  • 3、TERMINATED 表示线程已经运行结束,子线程运行完成、被打断、被中止,状态都会从 RUNNABLE 变成 TERMINATED;

  • 4、BLOCKED 表示线程被阻塞,如果线程正好在等待获得 monitor lock 锁,比如在等待进入 synchronized 修饰的代码块或方法时,会从 RUNNABLE 变成 BLOCKED;

  • 5、 WAITING 和 TIMED_WAITING 都表示等待,现在在遇到 Object#wait、Thread#join、 LockSupport#park 这些方法时,线程就会等待另一个线程执行完特定的动作之后,才能结 束等待,只不过 TIMED_WAITING 是带有等待时间的;

优先级

优先级代表线程执行的机会的大小,优先级高的可能先执行,低的可能后执行。

在 Java 源码中,优先级从低到高分别是 1 到 10,线程默认 new 出来的优先级都是 5,源码如下:

 /*** The minimum priority that a thread can have.*/public final static int MIN_PRIORITY = 1;/*** The default priority that is assigned to a thread.*/public final static int NORM_PRIORITY = 5;/*** The maximum priority that a thread can have.*/public final static int MAX_PRIORITY = 10;

线程的创建方式

我们创建多线程有两种方式,一种是继承 Thread 类,另一种是实现 Runnable 接口。两种方式的使用,如下所示:

1、继承 Thread,成为 Thread 的子类

public class MyThread extends Thread{@Overridepublic void run() {System.out.println("我是通过继承 Thread 类实现的~");}public static void main(String[] args) {MyThread thread = new MyThread();// 启动线程thread.start();}
}

2、实现 Runnable 接口

public class MyThread1 {public static void main(String[] args) {Thread thread = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("我是通过 runnable 方式实现的~");}});// 启动线程thread.start();}
}

不管使用哪一种方式,启动线程都是thread.start()方法,如果你做过实验的话,你会发现 thread.run()也可以执行,为什么就一定需要调用thread.start()方法呢

先说说结论:首先通过对象.run()方法可以执行方法,但是不是使用的多线程的方式,就是一个普通的方法,要想实现多线程的方式,一定需要通过对象.start()方法

想要弄明白一个问题,最好的办法就是从源码入手,我们也从这两个方法的源码开始,先来看看 start 方法的源码:

public synchronized void start() {/*** This method is not invoked for the main method thread or "system"* group threads created/set up by the VM. Any new functionality added* to this method in the future may have to also be added to the VM.** A zero status value corresponds to state "NEW".*/// 没有初始化,抛出异常if (threadStatus != 0)throw new IllegalThreadStateException();/* Notify the group that this thread is about to be started* so that it can be added to the group's list of threads* and the group's unstarted count can be decremented. */group.add(this);// 是否启动的标识符boolean started = false;try {// start0() 是启动多线程的关键// 这里会创建一个新的线程,是一个 native 方法// 执行完成之后,新的线程已经在运行了start0();// 主线程执行started = true;} finally {try {if (!started) {group.threadStartFailed(this);}} catch (Throwable ignore) {/* do nothing. If start0 threw a Throwable thenit will be passed up the call stack */}}
}

start 方法的源码也没几行代码,注释也比较详细,最主要的是 start0() 方法,这个后面在解释。再来看看 run() 方法的源码:

    @Overridepublic void run() {// 简单的运行,不会新起线程,target 是 Runnableif (target != null) {target.run();}}

run() 方法的源码就比较简单的,就是一个普通方法的调用,这也印证了我们上面的结论。

接下来我们就来说一说这个 start0() 这个方法,这个是真正实现多线程的关键,start0() 代码如下:

private native void start0();

start0 被标记成 native ,也就是本地方法,并不需要我们去实现或者了解,**为什么 start0() 会标记成 native **?

这个要从 Java 跨平台说起,看下面这张图:

图片来源牛客网

start() 方法调用 start0() 方法后,该线程并不一定会立马执行,只是将线程变成了可运行状态(NEW ---> RUNNABLE)。具体什么时候执行,取决于 CPU ,由 CPU 统一调度。

我们又知道 Java 是跨平台的,可以在不同系统上运行,每个系统的 CPU 调度算法不一样,所以就需要做不同的处理,这件事情就只能交给 JVM 来实现了,start0() 方法自然就表标记成了 native。

最后,总结一下,Java 中实现真正的多线程是 start 中的 start0() 方法,run() 方法只是一个普通的方法。

最后,再附上我历时三个月总结的 Java 面试 + Java 后端技术学习指南,这是本人这几年及春招的总结,目前,已经拿到了大厂offer,拿去不谢!

下载方式

1. 首先扫描下方二维码

2. 后台回复「Java面试」即可获取

Java 多线程启动为什么调用 start() 方法而不是 run() 方法?相关推荐

  1. python多线程没有java_Java 多线程启动为什么调用 start() 方法而不是 run() 方法?...

    多线程在工作中多多少少会用到,我们知道启动多线程调用的是 start() 方法,而不是 run() 方法,你知道原因吗? 在探讨这个问题之前,我们先来了解一些多线程的基础知识~ 线程的状态 Java ...

  2. 更新尺寸调用什么方法_Java 多线程启动为什么调用 start() 方法而不是 run() 方法?...

    多线程在工作中多多少少会用到,启动 多线程调用的是 start() 方法,而不是 run() 方法,这是为什么呢? 在探讨这个问题之前,先来了解(复习)一些多线程的基础知识~ 线程的状态 Java 中 ...

  3. 启动线程时使用 start 而不是 run

    今天团队里面的妹子问阿粉,为什么在启动线程的时候,都使用 start 方法,而不是 run 方法呢 还好阿粉平时一直有在学习,要不真的被妹子问住了 在多线程中,如果想让一个线程启动,你使用的方法一定是 ...

  4. C#开发笔记之03-为什么选择IsNotXXX方法而不是IsXXX方法?

    C#开发笔记概述 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/959 访问. 为什么有时候要选择IsNotXXX方法而 ...

  5. java线程开启不了_Java中多线程启动,为什么调用的是start方法,而不是run方法?...

    前言 大年初二,大家新年快乐,我又开始码字了.写这篇文章,源于在家和基友交流的时候,基友问到了,我猛然发现还真是这么回事,多线程启动调用的都是start,那么为什么没人掉用run呢?于是打开我的ide ...

  6. Java中多线程启动,为什么调用的是start方法,而不是run方法?

    前言 大年初二,大家新年快乐,我又开始码字了.写这篇文章,源于在家和基友交流的时候,基友问到了,我猛然发现还真是这么回事,多线程启动调用的都是start,那么为什么没人掉用run呢?于是打开我的ide ...

  7. Java 多线程:synchronized 关键字用法(修饰类,方法,静态方法,代码块)

    前言 在 多线程生成的原因(Java内存模型与i++操作解析) 中,介绍了Java的内存模型,从而可能导致的多线程问题.synchronized就是避免这个问题的解决方法之一.除了 synchroni ...

  8. Java多线程实现异步调用

    在Java平台,实现异步调用的角色有如下三个角色:调用者. 提货单 .真实数据,一个调用者在调用耗时操作,不能立即返回数据时,先返回一个提货单 .然后在过一断时间后凭提货单来获取真正的数据.去蛋糕店买 ...

  9. java多线程基本概述(二)——Thread的一些方法

    在Thread类中有很多方法值得我们关注一下.下面选取几个进行范例: 1.1.isAlive()方法 java api 描述如下: public final boolean isAlive() Tes ...

最新文章

  1. mysql datetime转换为date_MySQL date,datetime,timestamp区别及相互转换
  2. 【Flutter】插件包选择 ( 查看文档是否全面 | 查看插件包的更新版本次数 | 查看使用示例 | 查看 GitHub 项目的 Star Fork Issues )
  3. linux 目录/sys 解析
  4. 赌场圣手(从不失手)——隐马尔可夫!
  5. html中添加背景音乐的标签,添加背景音乐的html标签是什么
  6. 前端开发 get请求与post请求 0228
  7. javascript-自定义对象-数组形态对象-字典形态对象
  8. 抓包分析360浏览器和360搜索配对使用的安全性-WEB服务端分析
  9. 吴恩达深度学习5.2练习_Sequence Models_Operations on word vectors
  10. C++的RTTI基本原理
  11. 物联网单片机毕业设计实现
  12. 无人机动力测试台的应用-测试高转速下的无人机螺旋桨结冰和脱落
  13. 利用Python爬虫建立自己的磁力搜索引擎
  14. NAO机器人姿势切换
  15. 设计模式之 策略模式
  16. Mac 共享WiFi给任意设备(Android,Iphone等等)
  17. 古琴调音频率及音位图(正调F调)
  18. MinGW MinGW-W64介绍
  19. 【转载】浅谈蓝牙 Mesh 组网技术
  20. 【NDN实验】ndnSIM 2.0: A new version of the NDN simulator for NS-3 全文翻译

热门文章

  1. Oracle 游标(cursor) 说明
  2. getaddrinfo函数
  3. ESP8266编译脚本
  4. eui加载时间长_游戏加载时间越来越短了?背后藏着这些小心机
  5. A53 cache的架构解读
  6. Beyond Compare4长期使用方法
  7. CA/TA通信的share memory设计思想解读
  8. python的openpyxl库如何读取特定列_通过渲染一百万个网页,来了解网络是如何崩溃的...
  9. 【网络安全】如何使用QueenSono从ICMP提取数据
  10. 网安面试只要掌握这十点技巧,轻轻松松吊打面试官