多线程在工作中多多少少会用到,我们知道启动多线程调用的是 start() 方法,而不是 run() 方法,你知道原因吗?

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

线程的状态

Java 中,定义了 6 种线程状态,在 Thread 类可以找到: // 为了节约空间,我删除了注释

public enum State {

NEW,//初始状态

RUNNABLE,//运行状态

BLOCKED,// 阻塞状态

WAITING,//等待状态

TIMED_WAITING,//超时等待状态

TERMINATED;//终止状态

}

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

这张图描述的还是非常详细的,结合这张图,来说说这几种状态分别代表着什么意思: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{

@Override

public 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() {

@Override

public 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 then

it will be passed up the call stack */

}

}

}

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

public void run(){

// 简单的运行,不会新起线程,target 是 Runnable

if (target != null) {

target.run();

}

}

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

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

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

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

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

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

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

https://juejin.im/post/5eb67a9f6fb9a043753b5139

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

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

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:终于放弃了单调的swagger-ui了,选择了这款神器-knife4j个人原创100W+访问量博客:点击前往,查 ...

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

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

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

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

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

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

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

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

  6. 多线程编程java_Java多线程编程

    Java给多线程编程提供了内置的支持.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务. 多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销. ...

  7. 多线程编程 java_java多线程编程

    一.多线程的优缺点 多线程的优点: 1)资源利用率更好 2)程序设计在某些情况下更简单 3)程序响应更快 多线程的代价: 1)设计更复杂 虽然有一些多线程应用程序比单线程的应用程序要简单,但其他的一般 ...

  8. python的os,commands,subprocess启动进程调用的几种方法

    因为我碰到项目需求需要用python去调用jython的文件.因为虽然都是python家族,但是一个是java一个是c的,所以研究了下文件交互的方法,虽然结论不用这个模式,但是记录下这个经验. 一般最 ...

  9. 多线程共享java_java多线程之共享资源

    转载请注明出处 http://blog.csdn.net/pony_maggie/article/details/42587821 作者:小马 先看一个示例, 多个计数器线程实例(TwoCounter ...

最新文章

  1. plc单片机组态软件php_STC8单片机扩展WiFi通信实现功能与组态王组态软件详细组态...
  2. 在Visual C++中用ADO进行数据库编程(上)
  3. Java笔记-模拟QQ三方登录(单点登录2.0)
  4. 《从零开始学Swift》学习笔记(Day 16)——字典集合
  5. React 第十章 状态提升
  6. php系统如何连接数据库服务器,php如何连接数据库服务器
  7. 通讯框架 t-io 学习——给初学者的Demo:ShowCase设计分析
  8. word 段显示在页面最下方_最快速地把同一内容插入到Word文档不同页面的相同位置...
  9. kafka安装完整步骤_还在寻找Kafka最新的安装教程吗?精细的安装步骤分享给大家...
  10. 计算机信息管理的检索步骤,信息检索策略与步骤
  11. Echarts 三维地图
  12. GPT/GP2/GPT3
  13. 个人作业——软件产品案例分析
  14. 【微信小程序】Java岗面试12家大厂成功跳槽
  15. 怎样在matlab q-q图上读出斜率,Matlab的常见问题
  16. 8421码,5421码,2421码,余3码特点及转换
  17. MAX7219芯片 共阴LED驱动器 详细介绍
  18. 麦咖啡未来三年将投资25亿,在中国内地布局超过4000家
  19. PS 学习笔记 11--画笔工具
  20. Arduino 四位数码管控制

热门文章

  1. 【转】MyBatis缓存机制
  2. SQLServer存储过程编写规则
  3. Python基础7(集合与深浅copy)
  4. Gentle.NET 使用文档
  5. 强强联合,OpenCV搭载飞桨模型,帮你轻松玩转深度学习
  6. GNN 模型在生物化学和医疗健康中的典型应用
  7. 9行代码提高少样本学习泛化能力! ICLR2021 Oral,代码已开源
  8. 零基础程序员如何快速学会python
  9. 人生苦短,Python值得!这些Pandas隐藏小技巧你知道吗?
  10. 无意中发现的一份清华大佬的刷题笔记!