设计模式中的单例设计模式

关于单例设计模式有很多文章了,我还是想根据我的理解写一下,感觉这样记忆跟简单


单例设计模式按照调用的时间分为 懒汉式和饿汉是

1.懒汉式

1.1普通单例设计模式

public class MySingleton {  
      
    private static MySingleton instance = new MySingleton();  
      
    private MySingleton(){}  
      
    public static MySingleton getInstance() {  
        return instance;  
    }  
      
}  
构造方法进行私有化,则该类无法在外部类中实例化,同时提供了可以在外部类中访问的静态方法,

但是这样写在多线程中是不安全的,在并发情况下是有可能创建多个MySingleton 

1.2 双重检测锁定

   public static Singleton getInstance() {  
        if (singleton == null) {    
            synchronized (Singleton.class) {    
               if (singleton == null) {    
                  singleton = new Singleton();   
               }    
            }    
        }    
        return singleton;   
    }  

这样写在看着是多线程安全的,但是在java中是不可行的
 singleton = new Singleton(); 
执行的的过程有
1.分配内存空间
2.赋值,引用不再为空、
3.调用构造函数,初始化对象
其中2,3执行的顺序是不确定,这是因为java的内存模块式,指令重排。
线程A执行1-->2 程序跳出同步代码块,此时还没执行构造方法,此时第二个线程进入在第一判断中,判断不为空,直接返回。此时出现错误。

解决方法: 

1. 将对象使用声明成 volatile 的变量被认为是顺序一致的,即,不是重新排序的。但是试图使用 volatile 来修正双重检查锁定的问题,

注意:volatile禁止指令重排的语义,在JDK1.5之后修复,也就是在1.5之后使用volatile使用双锁检测时可以的

2.将类的创建,和返回类的对象分开

  public static void getInstance() {  
        if (singleton == null) {    
            synchronized (Singleton.class) {    
               if (singleton == null) {    
                  singleton = new Singleton();   
               }    
            }    
        }    
    }  

public static  Singleton instance(){
        if (manager == null){
            throw new IllegalStateException("你必须先调用 DataBaseManager.init(Context context, String dbName)");
        }
        return instance();
    }

3、静态内部类(推荐使用)

public class Singleton {    
    private static class LazyHolder {    
       private static final Singleton INSTANCE = new Singleton();    
    }    
    private Singleton (){}    
    public static final Singleton getInstance() {    
       return LazyHolder.INSTANCE;    
    }    
}    
在JVM的2内部机制保证了一个类被加载入时是线程互斥的,所以使用静态内部类保证了INSTANCE只会背创建一次,也保证了整个程序的效率


2.饿汉式

public class Singleton1 {  
    private Singleton1() {}  
    private static final Singleton1 single = new Singleton1();  
    //静态工厂方法   
    public static Singleton1 getInstance() {  
        return single;  
    }  
}  

饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的
但是这样的话,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值