1、类的加载机制:
每个编写的”.java”拓展名类文件都存储着需要执行的程序逻辑,这些”.java”文件经过Java编译器编译成拓展名为”.class”的文件,
”.class”文件中保存着Java代码经转换后的虚拟机指令,当需要使用某个类时,虚拟机将会加载它的”.class”文件,并创建对应的class对象,
将class文件加载到虚拟机的内存,这个过程称为类加载,这里我们需要了解一下类加载的过程。
=========================================================
2、类的加载过程:
------------------------|
| |
加载-- |->验证---->准备---->解析--|---->初始化
|----------链接----------|
==========================================================
*****加载:类加载过程的一个阶段:通过一个类的完全限定查找此类字节码文件,并利用字节码文件创建一个Class对象
*****验证:目的在于确保Class文件的字节流中包含信息符合当前虚拟机要求,不会危害虚拟机自身安全。
主要包括四种验证,文件格式验证,元数据验证,字节码验证,符号引用验证。
*****准备:为类变量(即static修饰的字段变量)分配内存并且设置该类变量的初始值即0(如static int i=5;这里只将i初始化为0,至于5的值将在初始化时赋值),
这里不包含用final修饰的static,因为final在编译的时候就会分配了,注意这里不会为实例变量分配初始化,类变量会分配在方法区中,而实例变量是会随着对象一起分配到Java堆中。
*****解析:主要将常量池中的符号引用替换为直接引用的过程。符号引用就是一组符号来描述目标,可以是任何字面量,
而直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄。有类或接口的解析,字段解析,
类方法解析,接口方法解析(这里涉及到字节码变量的引用,如需更详细了解,可参考《深入Java虚拟机》)。
*****初始化:类加载最后阶段,若该类具有超类,则对其进行初始化,执行静态初始化器和静态初始化成员变量(如前面只初始化了默认值的static变量将会在这个阶段赋值,
成员变量也将被初始化)。
----这便是类加载的五个过程,而类加载器的主要任务是根据一个类的全限定名来读取此类的二进制字节流到JVM中,然后转化为一个与此类对应的。class文件对象。
即字节码文件。在虚拟机中提供三种类加载器:引导类加载器(BootStrap),扩展类加载器(Extension),系统类加载器(System)(也称应用类加载器)。
=============== 类加载器的介绍===================
启动类加载器,由C++实现,没有父类。BootStrap;
拓展类加载器(ExtClassLoader),由Java语言实现,父类加载器为null
系统类加载器(AppClassLoader),由Java语言实现,父类加载器为ExtClassLoader
自定义类加载器,父类加载器肯定为AppClassLoader。
=======
所谓class文件的显示加载与隐式加载的方式是指JVM加载class文件到内存的方式,显示加载指的是在代码中通过调用ClassLoader加载class对象,
如直接使用Class.forName(name)或this.getClass().getClassLoader().loadClass()加载class对象。
而隐式加载则是不直接在代码中调用ClassLoader的方法加载class对象,而是通过虚拟机自动加载到内存中,
如在加载某个类的class文件时,该类的class文件中引用了另外一个类的对象,此时额外引用的类将通过JVM自动加载到内存中。
在日常开发以上两种方式一般会混合使用,这里我们知道有这么回事即可。
================线程的生命周期=========================
线程的生命周期:
1)新建状态:当创建Thread类的一个实例对象,此线程进入新建状态(未被启动)。例如:Thread t = new Thread();
2)就绪状态:线程已经被启动,等待cpu分配的时间片,也就是说此线程在就绪队列中中等待cpu资源。t.start();
3)运行状态:线程获得cpu资源,正在执行任务(run()),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束.
4)死亡状态:当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。
****自然终止:正常运行run()方法后终止。
****异常终止:调用stop()方法让一个线程终止运行。
5)阻塞状态:由于某种原因,导致线程让出cpu资源并暂停自己的任务,即进入阻塞状态。
****正在睡眠:用sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。
****正在等待:调用wait()方法。(调用notify()方法回到就绪状态)。
****被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复)。
--------------------------------------------------------------------
(1)结束线程原理:就是让run方法结束。而run方法中通常会定义循环结构,所以只要控制住循环即可
(2)方法----可以boolean标记的形式完成,只要在某一情况下将标记改变,让循环停止即可让线程结束
(3)public final void join()//让线程加入执行,执行某一线程join方法的线程会被冻结,等待某一线程执行结束,该线程才会恢复到可运行状态
--------------------------------
临界资源:多个线程共享的数据资源称为临界资源
(1)互斥锁
a.每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。
b.Java对象默认是可以被多个线程共用的,只是在需要时才启动“互斥锁”机制,成为专用对象。
c.关键字synchronized用来与对象的互斥锁联系
d.当某个对象用synchronized修饰时,表明该对象已启动“互斥锁”机制,在任一时刻只能由一个线程访问,
即使该线程出现堵塞,该对象的被锁定状态也不会解除,其他线程任不能访问该对象。