(4)单例模式--创建型
多种实现方式
- 饿汉式
- 懒汉式 (DCL必会)
- 枚举 (自己用推荐)
在多种实现方式下,需要注意多线程环境下线程安全问题。
首先,考虑如何确保单例?
1、如果在外部所有人都可以访问单例类的构造器,那就可以直接创建对象,所以构造器私有化。
2、构造器私有化了以后,只有自己可以创建对象,因此需要对外暴露一个方法getInstance(静态方法?原因外部没有实例,没有办法调用对象方法),让其他人获取对象。
3、由于全局唯一,不能创建多次,所以第一次创建完,需要保存到属性中,当下一次获取对象时,先去判断有没有该实例,有则直接返回该实例对象;并且由于getInstance
要访问该属性,所以属性加static进行修饰。原因:静态方法不能访问非静态属性,但是非静态方法可以访问静态属性。有类不一定有对象,有对象时,一定有类。
饿汉式(加载类时直接创建,懒汉式使用时才会创建)
线程安全,原因:类加载时属性初始化,且初始化一次。
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
懒汉式
非线程安全
public class Singleton {
private static Singleton singleton;
private Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
线程安全
//同步方法
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
//DCL 双检锁
public class Singleton {
// volatile 防止指令重排,
private volatile static Singleton singleton;
private Singleton() {
}
// DCL 双检锁
public static Singleton getSingleton(){
if(singleton == null){
synchronized (Singleton.class){
if (singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
// 枚举方式
public enum Singleton {
INSTANCE;
}