wait和sleep的区别
两者的作用都是让线程从运行态进入阻塞态
-
wait是Object类下的方法,sleep是Thread类中的static方法
-
sleep属于Time_Waiting状态,结束休眠后会自动唤醒,wait方法属于Waiting状态,需要手动唤醒
-
sleep在持有锁时执行,且不会释放锁资源,wait方法在执行后会释放锁资源
-
wait方法必须在持有锁时执行,wait方法会将持有锁的线程封装成node扔到waitSet中,这个操作需要调用ObjectMoniter对象的方法,如果没有持有synchronized锁的话就无法操作对象
Synchronized锁底层
synchronized是基于对象实现的锁,作用是保证多个线程访问资源的同步性,所以也叫做“同步锁”,在对象头中存储MarkWord,在MarkWord中又标记了在各个不同状态下要存储的一些信息
-
synchronized对于普通方法锁的是当前实例
-
synchronized静态同步方法,锁的是当前类的Class对象
-
synchronized对于同步代码块,锁的是synchronized括号配置的对象
原子性保证:monitorenter对锁对象关联累加标识已经被加锁,monitorexit递减计数器=0时表示该线程不持有锁
可见行,有序性保证:内存屏障
JVM,JDK,JRE区别
-
jvm指的是Java虚拟机,他的本质就是运行在操作系统上的一段程序,用来装载字节码文件,将他转化为被机器认识的机器码,屏蔽掉底层的硬件差异和指令层面的细节,是Java能够实现跨平台的关键
-
jre被称为Java运行时环境,里面配置了Java所运行时必须要的核心类库,内部包含了Java虚拟机
-
JDK又包含了jre,是Java的开发工具包,里面还包含了javac,javadoc,JavaAPI等工具,用于Java程序的开发和调试
Java半解释半编译
-
解释性语言:是按照特定规范的解释器将代码一句一句进行解释为机器代码再执行效率快速度慢
-
编译型语言:将代码一次性翻译为可执行的机器码语言,速度快,效率慢
Java程序分为先编译后解释,先由编译器编译为字节码文件,字节码文件经过Java虚拟机解释为可执行的机器码文件。
面向对象的理解
面向对象是相对与面向过程而言的一种程序设计思想,我们常说的面向对象是指并不注中方法的具体是实现步骤,而是从宏观的角度看待问题,将问题细化为一个个的对象,通过对象中的方法来完成功能
面向过程注重于问题的具体实现
类:是同一事物的相同属性的集合,是一个抽象的概念而对象是类的具体实现,创建对象的过程也叫做类的实例化过程
封装
将某些类信息通过private修饰,不让外部的方法直接访问到他,而是通过类中提供的方法进行访问,避免了外部操作对我们类的影响。隐藏了内部实现细节符合面向对象的思想
继承
通过super关键字实现子类继承父类,并且可以访问父类中的所有非私有的方法,提高代码的复用性
多态
同一事物在不同时刻表现不同的状态,可以通过继承父类或实现接口实现,从而在不同的类中表现出不同的功能,具体由方法多态和对象多态
方法多态:通过调用不同的参数来体现(方法重载),方法重写
对象多态:父类的引用执行子类的对象,对象的编译和运行类型可以不同
包装类
由于基本数据类型不具备面向对象的特性,例如无法实现进制转化,求最值.....因此Java对每个数据类型都做了相应的包装类,在jdk1.5之后就引入了自动装箱和拆箱
-
装箱 valueOf方法
-
拆箱 intValue方法
抽象类和接口
抽象类指的是由abstract修饰的类,类中可以包含抽象方法和普通的方法,抽象类的存在一定程度上可以反应Java的多态,不同的类集成抽象类并实现各自类中的方法
接口是一种特殊的抽象类,接口里只能含有抽象方法不能含有普通的方法,默认是被public static fianl修饰,实现接口时必须要实现接口中所有的抽象方法,否则就必须声明为抽象类
final关键字
-
final修饰的类不能够被集成
-
final修饰的方法不能被重写
-
final修饰的变量意为常量,值不能够改变
final,finally,finalize
finally:是在异常处理时使用到的一个关键字,表明该关键字内的内容无论是否出现异常我们都会执行,关闭流或者关闭连接时会被使用到
finalize:是Object类中的一个方法,在jvm确定不存在该对象的引用时调用该方法,在方法中你可以执行任何操作,但任何对象只能调用一次该方法。
深克隆和浅克隆
-
浅克隆:
-
深克隆
Object类中的方法
/**
* native 方法,用于返回当前运行时对象的 Class 对象,使用了 final 关键字修饰,故不允许子类重写。
*/
public final native Class<?> getClass()
/**
* native 方法,用于返回对象的哈希码,主要使用在哈希表中,比如 JDK 中的HashMap。
*/
public native int hashCode()
/**
* 用于比较 2 个对象的内存地址是否相等,String 类对该方法进行了重写以用于比较字符串的值是否相等。
*/
public boolean equals(Object obj)
/**
* native 方法,用于创建并返回当前对象的一份拷贝。
*/
protected native Object clone() throws CloneNotSupportedException
/**
* 返回类的名字实例的哈希码的 16 进制的字符串。建议 Object 所有的子类都重写这个方法。
*/
public String toString()
/**
* native 方法,并且不能重写。唤醒一个在此对象监视器上等待的线程(监视器相当于就是锁的概念)。如果有多个线程在等待只会任意唤醒一个。
*/
public final native void notify()
/**
* native 方法,并且不能重写。跟 notify 一样,唯一的区别就是会唤醒在此对象监视器上等待的所有线程,而不是一个线程。
*/
public final native void notifyAll()
/**
* native方法,并且不能重写。暂停线程的执行。注意:sleep 方法没有释放锁,而 wait 方法释放了锁 ,timeout 是等待时间。
*/
public final native void wait(long timeout) throws InterruptedException
/**
* 多了 nanos 参数,这个参数表示额外时间(以纳秒为单位,范围是 0-999999)。 所以超时的时间还需要加上 nanos 纳秒。。
*/
public final void wait(long timeout, int nanos) throws InterruptedException
/**
* 跟之前的2个wait方法一样,只不过该方法一直等待,没有超时时间这个概念
*/
public final void wait() throws InterruptedException
/**
* 实例被垃圾回收器回收的时候触发的操作
*/
protected void finalize() throws Throwable { }
String,StringBuffer,StringBuilder
string
实现了Serializable接口表明可以被序列化,实现Comparable接口表明可以比较大小,并且被final修饰不可被继承。底层是一个字符数组,每次修改字符串的值都会新创建一个新的字符串
stringbuffer
StringBuffer 是一个可变的字符串,对对象添加了同步锁所以线程安全,默认会创建一个数组,然后就向数组中添加元素,当数组存满了之后, 会扩容(创建新数组 把原来数组内容复制到新数组中),将新数组的地址赋给value, 不管拼接多少次,StringBuffer对象始终只创建另一个,底层大小为16,每次扩容都是2n+2的长度
stringbuilder
是单线程版本的stringbuffer,所以通常来说运行速度快于stringbuffer
字符串常量池
字符串常量池 是 JVM 为了提升性能和减少内存消耗针对字符串(String 类)专门开辟的一块区域,主要目的是为了避免字符串的重复创建。
intern方法
是一个本地方法,作用是将字符串对象的引用保存在常量池中
-
如果在常量池中有引用则直接返回
-
如果没有引用,则在常量池中创建一个指向该字符串的对象并返回
方法重载和方法重写
方法重载指的是参数的个数,类型,顺序只要有一个不同就满足方法重载
方法重写指的是子类继承父类后,重写父类中的方法,参数名,个数,返回值都必须一致,且权限不能低于父类
异常
所有的异常都有个公共的父类Throwable,他的下面有两个子类,一个是Exception,一个Error
Exception:程序中可以被处理的异常(编译期异常和运行时异常)
Error:Java虚拟机无法解决的严重问题,如JVM内部系统错误,资源耗尽等
throw和throws
throws:异常处理的一种办法,声明在方法处,后面跟异常类型
throw:手动生成异常对象的关键字,在方法体内,后面跟异常对象