图解线程帧

请看下面的代码

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 线程,分配线程栈


image.png

图2

CPU分配时间片 | 创建主线程栈帧 | 传入String数组到局部变量表 | 加载代码 method1的字节码|执行引擎解释成机器码| CPU 读取代码
在下文加载代码,解释机器码、CPU读取运行不在赘述。统称为加载代码


image.png

图3

创建method1栈帧 | 加载局部变量 x, y, m ,设置method1 返回地址为main调用代码地址 | x 设置 10 | 加载代码 int y=x+1 | CPU 读取代码 | y 设置11|加载代码 Object m= method2


image.png

图4

创建method2栈帧 | 加载局部变量n,设置method2 返回地址为method1代码地址 | 加载代码 Object n= new Object() | heap 创建 object 并把指针赋值给n |加载代码 return n


image.png

图5

销毁method2栈帧 | Object 指针赋值给m


image.png

图6

运行System.out.println(m) | 销毁method1 栈帧 |主方法没有代码,程序结束。


image.png

线程的上下文切换

因为以下原因导致cpu不再执行当前的线程,转而执行另外一个线程的代码

  • 线程的时间片用完

  • 垃圾回收

  • 有更高优先级的线程

  • 线程自己调用了 sleep、yield, wait、join、park、synchronized、lock 等方法
    当Context Switch发生时#需要由操作系统保存当前线程的状态.并恢复另一个线程的状态。Java中对应的概念就是程序计数8(Program Counter Register) #它的作用是记住下一条jvm指令的执行地址,是线程私有的。

  • 状态包括程序计数器,栈帧信息

  • Context 切换会影响性能

图7 : main 线程 cpu 时间分片结束,保存状态 | t1 开始运行

image.png

并发编程就是解决不同线程的依赖关系和逻辑关系

  1. 对共享对象的处理 - volatile

  2. 线程的协同和互斥 - lock

如果我们不指定堆栈的大小,JVM将创建一个默认大小的堆栈 (1m).

-XX:ThreadStackSize=1024 或者 -Xss1m。

问题:考虑内存分配大小,也需要考虑线程数量,来确定线程栈的大小。 Tomcat default 有多少个线程?**

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容