java单例模式

单例模式干的事情很简单,就是要保证某一个对象全局唯一。
对吗? 对不对要看标准
单例模式(Singleton Pattern):确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,
这个类称为单例类,它提供全局访问的方法。单例模式是一种对象创建型模式。
看来我之前定义的不全对。
第一 保证类只有一个实例
第二 类本身自己实例化(意思就是不能让别的类来new自己)
第三 提供全局访问的方法
OK 那我现在写出第一种Singleton

第一种Singleton

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Singleton{
     private static Singleton sl;
       //私有构造器避免了类在外部被实例化  
     private Singleton(){
        System.out.println(初始化);
     }
      
//Singleton的唯一实例只能通过getInstance()方法访问  
     public static Singleton getInstance(){
     if (sl== null )
          sl= new Singleton();
      return sl;
     }
     
     public static void main(String[] args){
         Singleton sl=Singleton.getInstance();
         Singleton sl2=Singleton.getInstance();
     }
}
运行结果是显示一个初始化
但是这里存在一个问题 如果多个线程同时运行这段代码,当第一个线程运行到sl=new Singleton()时(这一句还没有执行),第二个线程检查sl还是为null的,此时第二个线程也进来了... 然后就有多个对象了。

所以有

第二种Singleton

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/***
  * 饿汉模式
  */
public class Singleton2{
     private final static Singleton2 sl2= new Singleton2();
     private Singleton2(){
         System.out.println(初始化);
     }
     public static Singleton2 getInstance(){
         return sl2;
     }
     public static void main(String[] args){
         Singleton2 sl2=Singleton2.getInstance();
         Singleton2 sl3=Singleton2.getInstance();
     }
}
这种单例模式,我们在类加载的时候,就把类变量new出来。这种方式我们称之为饿汉模式。
首先饿汉问题解决了上面的线程问题。我最开始加载的时候就有了类变量了并且还只有一个,自然不会存在线程问题了。
但这里有个性能问题,不管我用不用这个单例类,它总会被加载内存中,因此性能是个问题。
上面说了这个模式叫饿汉模式,那自然有非饿汉模式(术语叫懒汉模式)。不过在这里我不太想和大家聊懒汉模式,太复杂,且不怎么用。
那有没有一种单例,既能解决第一个的线程问题,同时保持性能(其实第二种饿汉模式就不错了,就那一个类,能拖多少性能?就算有10个,100个也不是太多)呢?而且也不像我说的那个懒汉模式那么复杂呢?
答案是肯定的。有!

内部类模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Singleton3{
     private static class hold{
         private  final static Singleton3 sl3= new Singleton3();
     }
     private Singleton3(){
     System.out.println(初始化);
     }
     public static Singleton3 getInstance(){
           return hold.sl3;
     }
     public static void main(String[] args){
              Singleton3 sl3=Singleton3.getInstance();
          Singleton3 sl4=Singleton3.getInstance();
          System.out.println(sl3==sl4);
     }
}
关于内部类与static,final的分析,我们这里暂时不讲。
内部类的方式解决了上面所提的几个问题。
但也引出了一个不是问题的问题

内部类是java支持的,但是在别的语言中,不一定。

转载自程序员小董的专栏



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值