千家信息网

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

发表于:2025-11-11 作者:千家信息网编辑
千家信息网最后更新 2025年11月11日,这篇文章主要讲解了"Java多线程启动为什么调用的是start()方法而不是run() 方法",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Java多线
千家信息网最后更新 2025年11月11日Java多线程启动为什么调用的是start()方法而不是run() 方法

这篇文章主要讲解了"Java多线程启动为什么调用的是start()方法而不是run() 方法",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Java多线程启动为什么调用的是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() 方法后,该线程并不一定会立马执行,只是将线程变成了可运行状态(NEW ---> RUNNABLE)。具体什么时候执行,取决于 CPU ,由 CPU 统一调度。

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

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

感谢各位的阅读,以上就是"Java多线程启动为什么调用的是start()方法而不是run() 方法"的内容了,经过本文的学习后,相信大家对Java多线程启动为什么调用的是start()方法而不是run() 方法这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

线程 方法 状态 运行 源码 方式 优先级 普通 代码 就是 学习 不同 成功 代表 关键 内容 只是 对象 接口 标记 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 服务器查看用户操作记录 汽车软件开发工程师发展前景 web服务器及客户端原理 国际足联移动数据库 数据库进入单用户模式 天津软件开发驻场报价 加拿大的软件开发研究生 晚会网络安全陷阱 河南智慧工地管理平台软件开发 无线网络安全技术或协议有哪些 企业审批软件开发公司 格尚科技转型互联网 服务器管理分割磁盘 企业和服务器远程交互的工具 云帮手服务器连接 oracle更改数据库名 软件技术与计算机网络技术 图片在数据库中的存储 星际争霸服务器检索内容出不来 面试软件开发测试技能专长 数据库的脚本文件可以有多少个 sqlite数据库使用 建立先进典型数据库启动 sql数据库数据恢复BAK 魔兽世界最强部落服务器 保定帮帮团网络技术有限公司 k30s光明山脉小白测评数据库 北京冬奥会网络安全保障领导小组 服务器开机有蜂鸣声 烟台人游烟台网络技术
0