zoukankan      html  css  js  c++  java
  • 线程的运行原理

    一、栈与栈帧

    Java Virtual Machine Stacks (Java 虚拟机栈)
    我们都知道 JVM 中由堆、栈、方法区所组成,其中栈内存是给谁用的呢?其实就是线程,每个线程启动后,虚拟
    机就会为其分配一块栈内存。
    每个栈由多个栈帧(Frame)组成,对应着每次方法调用时所占用的内存
    每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法
    二、运行过程
        public static void main(String[] args) {
            method1(10);
        }
    
        static void method1(int x) {
            int y = x + 1;
            Object m = method2();
            System.out.printf(m.toString());
        }
    
        static Object method2() {
            Object n = new Object();
            return n;
        }
    }
    1.将编译好的字节码加载到jvm的方法区内存中
    2.jvm启动一个main的主线程,cpu核心就准备运行主线程的代码了,给主线程分配自己的栈内存【args、局部变量、返回地址、所记录】,每个线程的栈里面还有个程序计数器
    程序计数器的作用:当cpu要执行哪行代码了,就去这个里面去要
    3.把主方法的里面代码行放到程序计数器
    4.主方法调用的是method1的方法,为method1分配栈内存,里面存储这个方法里面局部变量,返回地址,这些变量是分配内存时,会把空间预留好
    5.将method1的第一行读到程序计数器让cpu执行
    6.methode1下一行调用method2()方法,创建他的栈内存
    7.把Object n = new Object()这行代码读取到计数器,在队中创建对象
    8.method2()将返回地址给m,方法执行完就可以释放掉method2()的栈内存
    9.一层层方法结束后,依次释放掉每个方法线程

     三、多线程执行逻辑

    public class frameTest {
    
        public static void main(String[] args) {
            //线程t1
            Thread t1 = new Thread(new Runnable() {
                @Override
                public void run() {
                    method1(20);
                }
            });
            t1.start();
            //主线程
            method1(10);
        }
    
        static void method1(int x) {
            int y = x + 1;
            Object m = method2();
            System.out.printf(m.toString());
        }
    
        static Object method2() {
            Object n = new Object();
            return n;
        }
    }
    

    对上面代码进行断点调试查看:

     两个线程的状态:

    三.线程上下文切换(Thread Context Switch)

    因为以下一些原因导致 cpu 不再执行当前的线程,转而执行另一个线程的代码
    1.线程的 cpu 时间片用完
    2.垃圾回收
    3.有更高优先级的线程需要运行
    4.线程自己调用了 sleep、yield、wait、join、park、synchronized、lock 等方法
    原理:
    1.当 Context Switch 发生时,需要由操作系统保存当前线程的状态,并恢复另一个线程的状态,Java 中对应的概念
    就是程序计数器(Program Counter Register),它的作用是记住下一条 jvm 指令的执行地址,是线程私有的
    2.状态包括程序计数器、虚拟机栈中每个栈帧的信息,如局部变量、操作数栈、返回地址等
    3.Context Switch 频繁发生会影响性能
     
     
     
     
  • 相关阅读:
    Java 获取字符串指定下标位置的值 charAt()
    Java 获取字符串长度 length()
    Java 字符串拼接 StringBuilder() StringBuffer
    ngBind {{}} ngBindTemplate
    什么是:before和:after?
    滚屏加载
    JavaScript 高程三读书笔记;
    angularjs 构建主页 内置过滤器、日期的格式化
    Angular实现递归指令
    JQuery获取浏览器窗口的可视区域高度和宽度,滚动条高度
  • 原文地址:https://www.cnblogs.com/hejunhong/p/12520714.html
Copyright © 2011-2022 走看看