从内存图来理解java是如何执行多线程的
一、内存图简介
众所周知,java类中的成员变量会保存到方法区、java运行时的方法会存入栈中,随之方法中的局部变量也是存储在栈中的,引用类型(new出来的对象)存储在堆内存中。下面用java内存中的方法区、栈内存、堆内存来演示java方法的执行过程。
首先定义一个Person类。
public class Person {
public int age;
public String name;
public void m1() {
}
public void m2() {
m3();
}
public void m3() {
}
public static void m4() {
}
}
此时我们的内存图中是这样的
再定义一个测试类
public class Test {
public static void main(String[] args) throws Exception{
Person person1 = new Person();
person1.m1();
}
}
此时我们的内存图中是这样的
二、单线程代码执行方式
启动Test类之后,开辟一个主线程栈,创建一个person1对象(储存在堆内存中且只携带类中的非静态成员)
随后person1对象调用m1方法,主线程栈从堆内存中的person1对象的地址中拷贝一份m1方法入栈
待m1执行完后,m1方法出栈,整个主线程的内容结束,方法依次出栈,创建的对象引用被销毁。
而堆内存中的person1对象如果没有在其他地方被引用,将会被回收。
main方法执行完毕
三、多线程代码执行方式
对Test类进行调整,让他有多个线程参与
public class Test {
public static void main(String[] args) throws Exception{
Thread thread1 = new Thread() {
@Override
public void run() {
Person person1 = new Person();
person1.m2();
}
};
Thread thread2 = new Thread() {
@Override
public void run() {
Person person1 = new Person();
person1.m3();
}
};
// -----------------------
thread1.start();
thread2.start();
Person person1 = new Person();
person1.m1();
}
}
执行到分割线时内存图如下所示
随后执行start方法将线程丢入就绪队列
由于线程1、2均进入就绪态。cpu随时可能分配时间片使其运行所以thread1、thread2中创建person1以及主线程中创建person1对象的先后顺序无法确定。可能在主线程中person1的对象已经执行完方法后被回收了thread1、2才开始创建,也可能三个person1对象同时存在。