参考:蚂蚁课堂
单例的实现方式
什么是单例设计模式?在内存中保证只有一个实例,每次调用都是对同一个实例进行操作
- 饿汉式:在class文件被加载的时候创建(因为怕饿)
- 懒汉式:只有在需要使用时,才会去创建(因为懒)
- 静态内部类:也是在class文件被加载时创建
- 双重检测锁:类似懒汉式
懒汉式Java代码
懒汉式线程不安全,一般都需要跟synchronized联用,用Singleton类上锁
/*懒汉式*/
class Singleton{
// 因为是单例,所以是static
private static Singleton singleton;
// 防止通过反射初始化
private Singleton() {}
public static Singleton getSingleton(){
// 如果没有创建过,就创建实例
if(singleton == null){
// 加锁,因为线程不安全
synchronized (Singleton.class){
singleton = new Singleton();
}
}
return singleton;
}
}
饿汉式Java代码
饿汉式天生线程安全,只有在.class文件加载时才会被创建
/*饿汉式*/
class Singleton{
// 不会再创建,定义成final
// 在class加载时,就new出来
private static final Singleton singleton = new Singleton();
public static Singleton getSingleton(){
return singleton;
}
}
静态内部类
由于使用了静态内部类,也是在.class文件加载时创建,类似于饿汉式
class Singleton{
// 标记检测是否创建过,防止通过反射方式创建
private static Boolean isExist = false;
Singleton(){
if (isExist == false) {
isExist = true;
} else {
throw new RuntimeException("单例禁止通过反射二次创建!");
}
}
// 静态内部类
public static class SingletonInstance(){
private static final Singleton singleton = new Singleton();
}
public static getInstance(){
return SingletonInstance.singleton;
}
}
最后一种方法,双重检测锁
用synchronized上锁,并且会在此判断singleton
class Singleton{
private static Singleton singleton;
Singleton(){
}
public static Singleton getInstance(){
// 双重检测锁
if(singleton == null){
synchronized(this){
if(singleton == null){
singleton = new Singleton();
}
}
}
}
}
在main方法测试
public static void main(String[] args) {
Singleton s1 = Singleton.getSinleton();
// Singleton.getInstance();
Singleton s2 = Singleton.getSinleton();
System.out.println(s1 == s2);
}
返回值都是:true
如何选择单例创建方式
如果不需要延迟加载单例,可以使用枚举或者饿汉式,相对来说枚举性好于饿汉式。
如果需要延迟加载,可以使用静态内部类或者懒汉式,相对来说静态内部类好于懒韩式。
最好使用饿汉式 ---- 摘自蚂蚁课堂