- 什么是单例设计模式?
单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类只有一个实例。即一个类只有一个对象实例。 - 具体实现:
-
将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
-
在该类内部产生一个唯一的实例化对象,并且将其封装为private static类型。
-
定义一个静态方法返回这个唯一对象。
1 饿汉模式
直接创建实例对象,无论是否需要创建
1.1 饿汉式单例
public class Singleton1 {
public static final Singleton1 INSTANCE = new Singleton1();
private Singleton1(){}
public static Singleton1 getInstance(){
return INSTANCE;
}
}
1.2 使用枚举类
枚举enum和静态代码块的特性相似,在使用枚举时,构造方法会被自动调用
private enum Singleton2{
private Singleton2 instance;
private Singleton2 (){//枚举类的构造方法在类加载时被实例化
instance = new Singleton2 ();
}
public Singleton2 getInstance(){
return instance;
}
}
1.3 使用 static 代码块
静态代码块中的代码在使用类的时候就已经执行了,所以可以应用静态代码块的这个特性的实现。
public class Singleton3 {
public static final Singleton3 INSTANCE;
static{
INSTANCE = new Singleton3();
}
private Singleton3(){}
public static Singleton3 getInstance() {
return INSTANCE;
}
}
2 懒汉模式
在调用的时候才去创建这个实例
2.1 延迟加载
延迟加载就是调用get()方法时实例才被创建,常见的实现方法就是在get方法中进行new实例化,但是这种方法不能保证线程安全。
public class Singleton4 {
private static Singleton4 instance;
private Singleton4(){}
public static Singleton4 getInstance(){
//线程不安全
if(instance == null){
instance = new Singleton4();
}
return instance;
}
}
当有多个线程同时要创建对象的时候,多个线程有可能都停止在第一个if判断的地方,等待锁的释放,然后多个线程就都创建了对象,这样就不是单例模式了。
2.2 双重校验锁
第一次检查instance是否被实例化出来,如果没有进入if块,某个线程取得了类锁,实例化对象前第二次检查instance是否已经被实例化出来,如果没有,才最终实例出对象。
public class Singleton5 {
private static Singleton5 instance;
private Singleton5(){}
public static Singleton5 getInstance(){
//双检锁
if(instance == null){
synchronized(Singleton5.class){
if(instance == null){
instance = new Singleton5();
}
}
}
return instance;
}
}
在多线程情形下,synchronized方法通常效率低,在对外的创建实例方法上加如 synchronized 关键字保证其在多线程中很好的工作。用双重判断来创建一个单例的方法,具有内存占用率高,效率高,线程安全,多线程操作原子性的优点。
2.3 使用静态内部类的方式创建单例
Singleton6 类被加载了,INSTANCE不一定被初始化。只有显式通过调用 getInstance() 方法时才会显式装载 Inner类,从而实例化 INSTANCE
public class Singleton6 {
private Singleton6(){
}
private static class Inner{
private static final Singleton6 INSTANCE = new Singleton6();
}
public static Singleton6 getInstance(){
return Inner.INSTANCE;
}
}