JVM 加载.java文件
.java和.class(类如何被加载)
首先通过javac将.java文件编译为字节码文件.class
javac Semp.java
java Semp
类加载器就是将.class文件加载到内存中,并将这些内容转化成方法区中的运行时数据结构
ClassLoader只负责class文件的加载,至于能否运行是由Execution Engine觉得的
以Car car1=new Car();为例子
- 编译javac Car.java得到Car.class (这是小class)
- 类加载器加载Car.class,将它从硬盘加载进内存jvm,从硬盘到方法区,形成运行时数据结构
- 加载到了方法区,那在方法区以什么样子存在呢?类模版 大Class
Car car1=new Car();
Car car2=new Car();
Car car3=new Car();
Car 是在方法区,是大Class模版
car1,car2,car3在栈中
= 是引用
new Boo(); 实例对象,堆
对象锁和类锁(通过其他知识点辅助理解)
对象锁:锁的是new Car();
类锁:锁的是Car
对象锁是用于对象实例方法,或者一个对象实例上的,类锁是用于类的静态方法或者一个类的class对象上的。我们知道,类的对象实例可以有很多个,但是每个类只有一个
class对象,所以不同对象实例的对象锁是互不干扰的,但是每个类只有一个类锁。但是有一点必须注意的是,其实类锁只是一个概念上的东西,并不是真实存在的,它只是用来帮助我们理解锁定实例方法和静态方法的区别的
体验不同的锁
锁同一个s对象
此时两个线程不会交替运行
code
public class Main {
public static void main(String[] args) {
String s="";
// write your code here
new Thread(new Runnable() {
@Override
public void run() {
int num=10;
System.out.println(this);
Thread.currentThread().setName("线程一");
synchronized (s){
while (num>0){
System.out.println(Thread.currentThread().getName()+": "+ num--);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
int num=10;
Thread.currentThread().setName("线程二");
System.out.println(this);
synchronized (s){
while (num>0){
System.out.println(Thread.currentThread().getName()+": "+ num--);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
}
}
输出
com.company.Main$1@6494f6e7
线程一: 10
com.company.Main$2@2dd12e59
线程一: 9
线程一: 8
线程一: 7
线程一: 6
线程一: 5
线程一: 4
线程一: 3
线程一: 2
线程一: 1
线程二: 10
线程二: 9
线程二: 8
线程二: 7
线程二: 6
线程二: 5
线程二: 4
线程二: 3
线程二: 2
线程二: 1
两个锁this
注意此时两个线程的this并不是指同一个对象,因此两个线程并不互斥,会交替运行
code
public class Main {
public static void main(String[] args) {
String s="";
// write your code here
new Thread(new Runnable() {
@Override
public void run() {
int num=10;
System.out.println(this);
Thread.currentThread().setName("线程一");
synchronized (this){
while (num>0){
System.out.println(Thread.currentThread().getName()+": "+ num--);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
int num=10;
Thread.currentThread().setName("线程二");
System.out.println(this);
synchronized (this){
while (num>0){
System.out.println(Thread.currentThread().getName()+": "+ num--);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
}
}
输出
com.company.Main$1@132f7c29
线程一: 10
com.company.Main$2@59ca08c
线程二: 10
线程一: 9
线程二: 9
线程一: 8
线程二: 8
线程一: 7
线程二: 7
线程二: 6
线程一: 6
线程二: 5
线程一: 5
线程二: 4
线程一: 4
线程二: 3
线程一: 3
线程二: 2
线程一: 2
线程二: 1
线程一: 1
Process finished with exit code 0