java设计模式详解----------单例模式

什么是单例模式(Singleton):

在程序中有些对象我只需要一个,比如说配置文件、工具类、日志、缓存、线程池等等对象;

当多个程序去调用一个配制文件的时候,实际上调用的是一个相同的配置文件,如果多个程序调用的是多个配置文件,那么每次修改文件,就会出现问题,这是不合理的,比如说可能导致占用过多资源,不一致等结果;

比如程序中的缓存日志等等我们只需要一个就可以了,我们如果想保证整个应用中某个实例有且仅有一个的话,我们就要使用到单例模式


应用场景:

当有些对象我们只需要一个就足够的时候,使用单例模式


作用:

保证整个程序中的某一个实例对象有且仅有一个


类型:


1.饿汉模式:

不管用户是否需要该对象,只要类加载了,就会去创建该单例模式的对象,即假设总是处于饥饿状态,所以就叫做饿汉模式
 
 
[java]  view plain  copy
  1. public class Singleton {  
  2.       
  3.     //1.将构造方法私有化,不允许外部直接创建对象  
  4.     //创建一个无参构造方法,并且把该构造方法设置为私有型  
  5.     //此步骤修改了默认的构造方法  
  6.     private Singleton(){}  
  7.       
  8.     //2.在类的内部创建唯一实例,使用private static实现(因为1中把构造方法私有化了)  
  9.     //static:把它变成类的静态成员,外部才能调用  
  10.     //private:为了控制访问安全,需要把它变成私有的,不允许外部直接访问  
  11.     //当类被加载时,被static修饰的东西就要初始化,这就是饿汉模式的体现  
  12.     private static Singleton singletonInstance = new Singleton();  
  13.       
  14.     //3.提供一个用于获取实例的方法,使用public static实现(因为2中把实例私有化了)  
  15.     //需要添加static变成类方法才能被外部调用;如果不添加static,它是对象,不是类方法,所以外部是访问不到的  
  16.     //根据面向对现象的封装性,创建一个静态公有的get函数,这样就能通过使用类名来直接获取该实例  
  17.     public static Singleton getSingletonInstance(){  
  18.         return singletonInstance;  
  19.     }  
  20. }  

2.懒汉模式:

当用户第一次使用的时候才创建,后面再使用就不需要创建了,只实例化一次,即假设它比较懒,使用才创建,不用不创建,而且只创建一次,所以叫做懒汉模式

[java]  view plain  copy
  1. public class Singleton {  
  2.       
  3.     //1.将构造方法私有化,不允许外部直接创建对象  
  4.     private Singleton(){}  
  5.       
  6.     //2.只声明类的实例,不要实例化  
  7.     //类加载的时候没有创建唯一实例  
  8.     private static Singleton singletonInstance;  
  9.       
  10.     //3.提供一个用于获取实例的方法  
  11.     //只有当用户获取的时候采取做判断,实例不存在,创建实例,实例存在,直接返回就可以了,这个也保证了单例  
  12.         //懒汉模式的体现  
  13.     public static Singleton getSingletonInstance(){  
  14.         if(singletonInstance==null){  
  15.             singletonInstance= new Singleton();  
  16.         }  
  17.         return singletonInstance;  
  18.     }  
  19. }  
测试代码:

[java]  view plain  copy
  1. public class Test {  
  2.   
  3.     //控制台的结果是:s1==s2  
  4.     public static void main(String[] args) {  
  5.         Singleton s1 = Singleton.getSingletonInstance();  
  6.         Singleton s2 = Singleton.getSingletonInstance();  
  7.         if(s1==s2){  
  8.             System.out.println("s1==s2");  
  9.         }else{  
  10.             System.out.println("s1!=s2");  
  11.         }  
  12.     }  
  13. }  
区别:

饿汉模式:加载类使比较慢(每次都要创建实例),但是运行时获得对象的速度比较快(因为在类加载的时候就已经实例化对象),线程安全

懒汉模式:加载类比较快(不需要创建实例),但是运行时获取对象的速度比较慢(因为每次都要去判断对象是否存在),线程不安全

懒汉模式中的线程安全问题:

从线程安全方面来考虑,不使用同步的懒汉模式是线程不安全的

举例:假如从线程A开始进入,判断singletonInstance为空,此时就会创建一个实例对象,

            然后CPU进行切换,此时进来的是线程B,再对singletonInstance进行判断,依然为空,此时又会创建一个实例对象,

            然后CPU又切换到线程A继续创建实例,这时就会初相见两个实例

所以为了安全的使用单例模式,要不选择使用饿汉模式在类加载时创建实例,要不就使用同步锁的懒汉模式

懒汉模式线程安全的代码:

使用的是双重检查锁定

[java]  view plain  copy
  1. public class Singleton {  
  2.       
  3.     private Singleton(){}  
  4.       
  5.     private static Singleton singletonInstance;  
  6.       
  7.     public static Singleton getSingletonInstance(){  
  8.         if (singletonInstance == null) {      
  9.             synchronized (Singleton.class) {      
  10.                if (singletonInstance == null) {      
  11.                    singletonInstance = new Singleton();     
  12.                }      
  13.             }      
  14.         }      
  15.         return singletonInstance;  
  16.     }  
  17. }  


要点总结:
1.单例模式确保程序中一个类最多只有一个实例;
2.单例模式也提供访问这个实例的全局点;
3.在Java中单例模式需要有私有构造器、一个静态方法、一个静态变量;
4.确定性能和资源上的限制,然后小心的选择适当的方案来实现单例,以解决多线程问题;
5.双重检查加锁需要再JDK1.5及其以后的的版本才有效果;
6.如果使用多个类加载器,可能导致单例失效而产生多个实例;
7.如果使用JVM1.2及其以前的版本,必须建立单例注册表,以免垃圾收集器将单例回收。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值