执行流程
- 我们从一个简单的启动线程开始看
public static void main(String[] args){ new Thread(){ @Override public void run() { super.run(); } }.start(); }
这是一个最基础的线程启动方法,我们点进去看下
我们看下上面的这部分代码
- 第一步校验线程的状态,我们知道线程的状态从new->running,他这新的线程标识为0,也就是说非0的线程不启动,抛出异常
- group.add 将线程加入到group组中,这个group组是呈递减的
- 在下面的核心方法 try{}中的start方法
- -start方法我们从上图也能看到最终执行了一个Native方法 start0,也就是说他是JDK提供的
so,我们来看JDK源码中的对这个方法的具体实现
JDK 中的实现
打开JDK源码,jdk/src/share/native/java/lang/Thread.c,找到start0
我们知道与之对应的在JVM中的方法为StartThread,再找到JVM中的这个方法
相应的代码我们在hotspot下,在这个路径 jdk/src/share/native/java/lang/Thread.c
我们看下这个方法
核心就是这一段
创建了一个javaThread的对象
我们看到这个对象创建经过初始化后,通过 os::create_thread创建
所谓的OS就是不同系统下创建的方式,我们看到有Linux,windows等,我们来看Linux
这个文件里有个pthread_create(),查看下Linux的文档
The pthread_create() function starts a new thread in the calling process. The new thread starts execution by invoking start_routine(); arg is passed as the sole argument of start_routine().
The new thread terminates in one of the following ways
这是唯一创建线程的一个方法,OK。看到这我们也就明白了,每次我们start一个线程,最终我们都会在操作系统中创建一个线程
总结
从上面的源码的创建流程我们看到,最终用户态线程和内核态的关系是1:1。线程有自己的独立的栈,调度也依赖操作系统。
从前几篇文章我们分析了操作系统的线程模型后,我们知道系统调用的消耗是异常消耗资源的。在早期计算机的发展过程里是没有对多线程提供支持的。
Linux 中进程与进程之间有各自独立的数据空间(堆和栈,非亲戚进程还是独立的程序代码),进程本身占用的资源以及它们之间的交互都相对重量级。而线程的概念可以简单的认为是,相对独立的一个执行流,同时它们之间可以共享应用程序的大部分数据结构