Thread线程原理解析

1、构造函数

在这里插入图片描述

2、启动线程

启动线程很简单,只需要new Thread,实现run方法,调用start即可以启动线程
在这里插入图片描述

3、构造函数深入

Thread线程的构造函数很多,但最终都会进入到该初始化方法中
在这里插入图片描述

3.1、线程组

ThreadGroup g:线程组,如果不指定,则默认使用父线程的线程组
在这里插入图片描述
在这里插入图片描述
发现两个线程的线程组结果都是‘main’线程

3.2、Runnable

Runnable target:run的业务实现体,start将会调用对象的run方法,如果target==null,即该线程的实现为空,则不会执行。(开辟线程只有Thread一种,Runnable、Callable、线程池都是需要Thread去构造start去启动线程
在这里插入图片描述

3.2、线程名称

String name:线程的名称,如果不指定则默认以‘Thread-从0开始的计数器’为名称。
在这里插入图片描述
而计数器则是以static标识的int类型,即加载Thread类的时候只会初始化一次计数器,之后创建的线程则会累加。
在这里插入图片描述

3.3、线程栈深度

long stackSize:新线程的堆栈空间大小,默认为0,表示忽略该参数,同时又是与平台相关的。
在这里插入图片描述
如图代码中,线程中run调用了一个递归方法,一直累加计数,结果如下图,栈溢出。main线程是JVM虚拟机自动开辟的线程,stackSize我们指定不了。
在这里插入图片描述
而什么是栈溢出呢?当我们执行迭代方法时,进入一次方法就会压一次栈,直到栈超出了指定的栈深度。如果不使用迭代,而只是简单的累加,则不会有任何情况发生。
在这里插入图片描述
如果stackSize过高:超过JVM,则为JVM最大值,同时存活的线程数低。
如果stackSize过低:低于JVM,则为JVM最小值,同时存活的线程数高。
且过高过低会导致平台可能不支持该参数。

3.4、AccessControlContext

默认值为AccessController.getContext(),返回的类为AccessControlContext,该类是一个对security权限上下文进行了封装的一个类,能够对资源进行决策是否有权限。

该类有众多方法,但对权限上下文封装的public方法只有一个:
在这里插入图片描述
从方法名字看,是对系统某些保护的权限(context)进行检测是否有权限,如果没有权限,则会抛出AccessControlException权限不足的异常。在AccessControlContext的checkPermission方法中:
在这里插入图片描述

3.5、inheritThreadLocals

是否继承父线程的ThreadLocals:默认是true,在初始化线程时,默认会执行ThreadLocal.createInheritedMap去继承父线程的ThreadLocals。
在这里插入图片描述
继续追踪,找到了关键的几行代码,将父线程的ThreadLocalMap的table赋值到本线程中,且对父线程所有的ThreadLocal进行childValue处理(此处只是直接将值返回,只是方法名易于区分),将新的值从新赋值到table中。
在这里插入图片描述
主要作用是将父线程的信息进行传递给子线程。

3.6、构造函数中的其它处理

daemon线程:默认继承父类的守护线程,如果父类不是守护线程,则通过在调用start前设置setDaemon(true),当系统中只剩下守护线程时会自动退出。

priority优先级:默认继承父类的线程优先级,设置后线程执行时,CPU会优先执行该线程逻辑(不一定,只是概率高了,执不执行还得看CPU脸色啊!)

tid线程id:由 tid = nextThreadID();创建,该值为系统static变量,且唯一。

4、start原理

当构造完一个线程后,线程不会立即被创建,而是要调用线程对象的start方法。调用后会将threadStatus变量更改,如果启动后任然调用start方法,则会抛出IllegalThreadStateException异常
在这里插入图片描述
在这里插入图片描述
此时才是开辟线程的关键代码
在这里插入图片描述
线程启动需要调用start()方法,内部调用了start0()方法,该方法为本地方法区代码,由JVM自动调用,最终会执行Runnable的run方法
在这里插入图片描述在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章