SingleTon-单例设计模式
2021-05-21 本文已影响0人
AIGame孑小白
懒汉式
之所以叫做懒汉式:只有对象调用方法的时候才会获取到实例对象,所以懒。
大致雏形
public class SingleTon {
private static SingleTon singleTon;
public SingleTon(){}
public static SingleTon getInstence(){
if(singleTon==null){
singleTon = new SingleTon();
}
return singleTon;
}
}
采用DCL双重检测的写法,第一层if是提高效率,synchronized是为了保证实例化的对象在多线程并发访问的时候保持唯一性,第二层if则是判断是否需要创建实例对象。
最终成品
public class SingleTon {
private static SingleTon singleTon;
public SingleTon(){}
public static SingleTon getInstence(){
if(singleTon==null){
synchronized (SingleTon.class) {
if(singleTon==null){
singleTon = new SingleTon();
}
}
}
return singleTon;
}
}
弊端就是:由于添加了锁,所以降低了效率。
饿汉式
public class SingleTon {
private static SingleTon singleTon = new SingleTon();
public SingleTon(){}
public static SingleTon getInstence(){
return singleTon;
}
}
即解决了多线程同时访问造成对象不唯一,也解决了加锁使得效率低的问题。
第一种
public class SingleTon {
private static final SingleTon INSTANCE = new SingleTon();
//保证不让外界new出对象
private SingleTon(){}
public static SingleTon getInstance(){
return INSTANCE;
}
}
这种写法是饿汉式写法,饥饿难耐,恨不得自己创建对象。这种设计是线程安全的,实际上这是由JVM保证的,因为JVM加载所有类它都只load一次。这种写法简单实用。
第二种
public class SingleTon {
private static SingleTon INSTANCE;
private SingleTon(){}
public static SingleTon getInstance(){
if(INSTANCE==null){
INSTANCE = new SingleTon();
}
return INSTANCE;
}
}
这种写法被称之为:懒汉式,因为它是在外界调用get的时候创建的对象。但是当多线程并发访问的时候可能会导致多次创建对象。
第三种
public class SingleTon {
//volatile:避免指令重排(JIT优化)
private static volatile SingleTon INSTANCE;
private SingleTon(){}
public static SingleTon getInstance(){
if(INSTANCE==null){
synchronized(SingleTon.class){
if(INSTANCE==null){
INSTANCE = new SingleTon();
}
}
}
return INSTANCE;
}
}
DCL写法,双重检查锁写法,保证了线程安全,但是效率低了。
第四种
public enum SingleTon {
INSTANCE;
public void method(){
System.out.println("嘿嘿");
}
public static void main(String[] args) {
System.out.println(SingleTon.INSTANCE);
}
}
枚举单例:避免反序列化,避免线程安全问题(一种很完美的写法),但是我们实际开发中,还是使用最合适的那种。
在实际开发中,一般是把单例交给Spring的bean来解决,我们很少直接写。