请看下面的代码
package com.conrrentcy.thread;
public class TestFrame {
public static void main(String[] args){
method1(10);
}
public static void method1(int x){
int y = x+1;
Object m = method2();
System.out.println(m);
}
public static Object method2(){
return new Object();
}
}
本文将介绍 这个代码到底是怎么执行的。线程所有的操作都由执行引擎完成,类被加载到方法区候,它的代码指令被存到attbiute字段 code 区,类的的命名空间是classloader。
图1
类加载字节码(文中以代码示例),开启main 线程,分配线程栈
图2
CPU分配时间片 | 创建主线程栈帧 | 传入String数组到局部变量表 | 加载代码 method1的字节码|执行引擎解释成机器码| CPU 读取代码
在下文加载代码,解释机器码、CPU读取运行不在赘述。统称为加载代码
图3
创建method1栈帧 | 加载局部变量 x, y, m ,设置method1 返回地址为main调用代码地址 | x 设置 10 | 加载代码 int y=x+1 | CPU 读取代码 | y 设置11|加载代码 Object m= method2
图4
创建method2栈帧 | 加载局部变量n,设置method2 返回地址为method1代码地址 | 加载代码 Object n= new Object() | heap 创建 object 并把指针赋值给n |加载代码 return n
图5
销毁method2栈帧 | Object 指针赋值给m
图6
运行System.out.println(m) | 销毁method1 栈帧 |主方法没有代码,程序结束。
线程的上下文切换
因为以下原因导致cpu不再执行当前的线程,转而执行另外一个线程的代码
线程的时间片用完
垃圾回收
有更高优先级的线程
线程自己调用了 sleep、yield, wait、join、park、synchronized、lock 等方法
当Context Switch发生时#需要由操作系统保存当前线程的状态.并恢复另一个线程的状态。Java中对应的概念就是程序计数8(Program Counter Register) #它的作用是记住下一条jvm指令的执行地址,是线程私有的。状态包括程序计数器,栈帧信息
Context 切换会影响性能
图7 : main 线程 cpu 时间分片结束,保存状态 | t1 开始运行
并发编程就是解决不同线程的依赖关系和逻辑关系
对共享对象的处理 - volatile
线程的协同和互斥 - lock
如果我们不指定堆栈的大小,JVM将创建一个默认大小的堆栈 (1m).
-XX:ThreadStackSize=1024 或者 -Xss1m。
问题:考虑内存分配大小,也需要考虑线程数量,来确定线程栈的大小。 Tomcat default 有多少个线程?**