Thread源码解析---创建线程流程、start()之后回调run()方法流程

本文详细解析了Java中创建线程的两种方式,包括继承Thread类和实现Runnable接口,并深入源码探讨了Thread无参及有参构造方法的流程,特别关注了线程命名、线程组和可继承的线程局部变量。接着,分析了Thread的start()方法启动线程的过程,从start0()本地方法到JVM层面的JVM_StartThread,最终如何回调run()方法。通过对源码的解读,揭示了Java线程从创建到执行的底层机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、线程的两种创建方式

  1. 继承Thread类:通过new MyThread();无参构造方法创建对象;【MyThread是Thread类的继承类】
  2. 实现Runnable接口:通过new Thread(new MyThread());有参构造方法创建对象;【MyThread是Runnable接口的实现类】

 

二、Thread源码创建Thread对象流程

 

  1. 无参构造方法和有参构造方法:两个构造方法都是调用init()方法【init有很多重载方法】

 

  1. 查看第一步中的nextThreadNum()方法:为没有名字的线程自动编码,并且加锁,保证默认生成的名字不会重复。【名字是可以重复的,id不能重复】

  1. 查看第一步中init()方法:
  • group:指定当前线程的线程组,未指定时线程组为创建该线程所属的线程组。【通常为null】
  • target:指定运行其中的Runnable。【当是无参构造方法时,为null】
  • name:线程的名称,不指定自动生成。【默认为"Thread-n"】
  • stackSize:预期堆栈大小,不指定默认为0,0代表忽略这个属性。【与平台相关,一般不用】

 

  1. 查看上一步中的init()方法:
  • AccessControlContext:该值为null,表示用当前调用堆栈快照(AccessControlContext)初始化线程。
  • inheritThreadLoclas:该值为true,表示从构建线程继承可继承的线程局部变量初始值。

 

  1. 查看上一步中的init()方法:这是主要的init()方法,Thread的所有构造方法都会调用该方法。【部分重要代码】
// 最主要的辅助构造函数,所有的构造函数均调用init函数

private void init(ThreadGroup g, Runnable target, String name,

long stackSize, AccessControlContext acc,

boolean inheritThreadLocals) {

this.name = name;

Thread parent = currentThread();//当前线程为父线程

this.group = g;

//子线程继承父线程的守护属性

this.daemon = parent.isDaemon();

//子线程继承父线程的优先级

this.priority = parent.getPriority();

//当通过Runnable接口创建线程时,target就是用来保存传入的Runnable实现类的对象

//【Thread类会在重写的run方法中调用target对象的run方法】

//当通过Thread实现类创建线程时,target为null,因为Thread类的run方法以及被重写

this.target = target;

setPriority(priority);

this.stackSize = stackSize;

//获取唯一的线程id,此方法为static synchronized,保证了一个每个线程的id一定不一样

tid = nextThreadID();

}

完整代码见附件:

init.java

 

三、Thread源码start()之后回调run()流程

  1. start()方法源码:该方法调用了native的start0()方法

 

  1. Thread类要调用本地方法,首先要向jvm注册,所以Thread类的开头便是:

 

  1. 本地方法 start0定义在src\java.base\share\native\libjava\Thread.c文件中,定义了各个操作系统都要用到的关于线程的公用数据和操作:从methods[]中可以看出start0调用了JVM_StartThread方法

 

  1. 在src\hotspot\share\prims\jvm.cpp文件中有如下代码段:这里JVM_ENTRY是一个宏,用来定义JVM_StartThread函数,可以看到函数内通过JavaThread()创建了真正与平台相关的本地线程。

 

  1. 函数JavaThread()定义在src\hotspot\share\runtime\thread.cpp文件中:JavaThread()方法通过平台API创建线程

  1. 函数*thread_entry也在src\hotspot\share\prims\jvm.cpp文件中定义,代码如下:可以看见该函数调用了vmSymbols::run_method_name()。【就是这个调用了run方法】

  1. 函数run_method_name()定义src\hotspot\share\classfile\vmSymbols.hpp文件中:对应Thread或Thread实现类中的run方法。

 

  1. Java 线程调用关系图:Java线程的start方法会创建一个本地线程(通过调用JVM_StartThread函数中的JavaThread()),该线程的线程函数是定义在jvm.cpp中的JavaThread(),由thread_entry再进一步回调run方法。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值