目录
单例模式
概念:顾名思义就是只有一个实例,并且它自己负责创建自己的对象,这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象
特点:类构造器私有,持有自己类型的属性,对外提供获取实例的静态方法
懒汉式
特点:在需要获取实例对象的时候才去加载
问题:不是线程安全,同时两个线程进行获取实例对象时有可能获取到不同的对象
package com.anran.example.Singleton;
public class LazyMode {
/**
* 静态的自身对象
*/
private static LazyMode lazyModes;
/**
* 私有构造方法
*/
private LazyMode() {
}
/**
* 唯一获取当前对象实例的静态方法
* @return
*/
public static LazyMode getInstance(){
if (null == lazyModes) {
lazyModes = new LazyMode();
}
return lazyModes;
}
}
饿汉式
特点:在系统加载的时候就会对实例对象进行创建
问题:线程安全,但是浪费了内存空间
package com.anran.example.Singleton;
public class StarvingMode {
private static StarvingMode starvingModes = new StarvingMode();
private StarvingMode(){
}
public static StarvingMode getInstance(){
return starvingModes;
}
}
双重锁模式
描述:对实例对象进行加锁操作和原子操作,保证多线程在创建对象时阻塞
特点:做到了线程安全,延迟初始化,并且多线程并发时高效
volatile :保证创建对象时jvm的底层操作不会出现指令重新排序,从而保证第二个线程判断实例对象是否创建时的准确性
package com.anran.example.Singleton;
public class DoubleCheckModel {
private static volatile DoubleCheckModel doubleCheckModel;
private DoubleCheckModel(){
}
public DoubleCheckModel getInstance(){
if (null == doubleCheckModel) {
synchronized (DoubleCheckModel.class) {
if (null == doubleCheckModel) {
doubleCheckModel = new DoubleCheckModel();
}
}
}
return doubleCheckModel;
}
}
静态内部类模式
描述:在获取 实例对象的时候,虚拟机才去加载静态内部类并初始化,此时只有一个线程可以获得对象的初始化锁,其他线程无法进行初始化,保证对象的唯一性
特点:线程安全,延迟加载
package com.anran.example.Singleton;
public class StaticClassMode {
private StaticClassMode() {
}
public static StaticClassMode getInstance(){
return Inner.staticClassMode;
}
private static class Inner{
private static final StaticClassMode staticClassMode = new StaticClassMode();
}
}
枚举模式
特点:枚举类隐藏了私有的构造器,枚举类的域 是相应类型的一个实例对象
package com.anran.example.Singleton;
public enum EnumMode {
// 实例对象
INSTANCE;
// 可以补充其他操作
// 获取实例对象
public static EnumMode getInstance() {
return EnumMode.INSTANCE;
}
}
volatile关键字
保证对象创建在JVM中的执行过程中不会指令重新排序(原子操作)
JVM在创建对象的时候大致可以概括为(分配内存空间,初始化对象,外部引用指向内存空间),但在jvm实际执行的时候可能因为指令重新排序变成(分配内存空间,外部引用指向内存地址,初始化对象),此时可能导致对象没有创建完成就被后续程序使用,导致未知异常。