第一章-多线程-03-线程的核心原理
author:陈镇坤27
日期:不知道
文章目录
——————————————————————————————
CPU时间片
现代操作系统具备强大的线程管理能力,java越来越多地选择将线程的调度交给操作系统的调度进程去完成。
什么是CPU时间片
不同机器的CPU将自身的时间按毫秒进行分段。线程获得CPU时间片,即获得CPU调度的时间。
例如:2GHz的CPU,每秒计算20亿次,如果该CPU时间片长度为20ms,则每个CPU时间片能计算的次数为4000万次。
主流线程调度方式
获得CPU时间片的线程处于运行状态,而没得到时间片的线程则处于就绪状态。
线程调度模型
什么是分时调度模型?
系统平均分配CPU时间片给所有线程。
什么是抢占式调度模型?
系统按照线程优先级随机分配CPU时间片给线程。
(主流,这也是为什么Java的线程有优先级调度的原因)
线程优先级
Thread中的属性priority表示线程优先级。
默认值5,最小值1,最大值10,(这三个值都有对应的常量可以使用)数字越大,优先级越高,与之对应的线程获得执行机会更多,但也仅是获得执行的机会,事实上执行次数的多寡,是系统随机的。
线程的生命周期
在Thread内部有一个的公共枚举类State表示Thread的状态
Thread实例后状态为NEW;
start后状态为RUNNABLE;
代码执行结束(或抛异常)则状态转为TERMINATED;
如果调用Thread.sleep、Object.wait:抢占对象监视锁、Thread.join:线程合并、LockSupport.parknanos:让线程等待n纳秒、LockSupport.parkUntil:让线程等待n 单位时间 等方法,则状态转为TIMED_WAITING状态
线程的RUNNABLE与操作系统的RUNNABLE的差异
JVM线程的RUNNABLE不代表操作系统的RUNNABLE。
JVM的RUNNABLE代表就绪或运行。而操作系统的则代表运行。
实际上,JVM将线程调度通过JNI本地调用来委派给操作系统的线程管理API,而在start后,操作系统便进入就绪状态,等待获取CPU时间片,获取到时,则进入运行状态,时间片用完,如果代码逻辑还没结束,则又回到就绪状态,循环往复,直到最后的TERMINATED
使用Jstack查看线程状态
操作
jstack <pid> // pid为进程id
作用
打印jvm实例的线程快照,即打印jvm实例中每个线程正在执行方法的堆栈集合。
目的
分析线程间死锁、死循环、请求外部资源导致的长时间等待等。
注意
实际操作中,需要至少三次dump出日志进行分析;
不同的虚拟机,虚拟机的不同版本dump的日志都可能不一样;
操作结果例图及解释
如图包含GC线程、VM Periodic Task线程(周期性任务调度(内存、JVM运行状况监控)线程),二者随JVM启动产生;
tid:java实例线程id;
nid:对应的操作系统线程id;
prio:java实例线程优先级;
os_prio:对应的操作系统线程的优先级;