设计模式之——单例模式
java语言里面有三种经典的设计模式:单例模式、工厂模式、代理模式。
一、单例模式:
单例模式所解决的问题是:保证一个类在内存中的对象唯一性。
单例模式特点:
1、一个类只实例化一个对象,保证对象唯一性
2、构造器私有化
3、必须自行创建这个实例
4、必须向整个系统提供这个实例,即有一个public修饰的方法。
单例模式有多中写法,其中饿汉式和懒汉式比较常用。
一、饿汉式单例模式:(线程安全)
1 public class SingelModel{
2 private static SingelModel singel=new SingelModel();
3 private SingelModel(){}
4 public static SingelModel getInstance(){
5 return singel;
6 }
7 }
饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。
二、懒汉式单例模式:(非线程安全)
1 public class SingelModel {
2 private static SingelModel singel=null;
3 private SingelModel(){}
4 public static SingelModel getInstance(){
5 if(singel=null){
6 singel=new SingelModel();
7 }
8 return singel;
9 }
10 }
SingelModel 通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,SingelModel 的唯一实例只能通过getInstance()方法访问。
但是以上懒汉式单例的实现没有考虑线程安全问题,它是线程不安全的,并发环境下很可能出现多个Singleton实例,要实现线程安全,有以下三种方式,都是对getInstance这个方法改造,保证了懒汉式单例的线程安全。
二(一)、懒汉模式,在getInstance方法上加同步
1 public class SingelModel{
2 private static SingelModel singel=null;
3 private SingelModel(){}
4 public static syhcronized SingelModel getInstance(){
5 if(singel==null){
6 singel=new SingelModel();
7 }
8 return singel;
9 }
10 }
在方法调用上加了同步,虽然线程安全了,但是每次都要同步,会影响性能,毕竟99%的情况下是不需要同步的
二(二)、懒汉模式,双重检查锁定
1 public class SingelModel{
2 private static SingelModel singel=null;
3 private SingelModel(){}
4 public static SingelModel getInstance(){
5 if(singel==null){
6 synchronized(SingelModel.class){
7 if(singel==null){
8 singel=new SingelModel();
9 }
10 }
11 }
12 return singel;
13 }
14 }
在getInstance中做了两次null检查,确保了只有第一次调用单例的时候才会做同步,这样也是线程安全的,同时避免了每次都同步的性能损耗。这两种懒汉式即实现了线程安全,又避免了同步带来的性能影响。
饿汉式和懒汉式区别:
饿汉式就是类一旦加载,就把单例初始化完成,保证了在调用getInstance()方法时单例已经存在。
懒汉式就是比较懒,只有在调用getInstance()方法时才去初始化这个单例。
关于线程安全:
饿汉式时天生的线程安全,可以直接用于多线程而不用考虑会出现问题。
懒汉式本身并不是线程安全的,为了安全才会有上面两种写法在getInstance方法上加同步,双重检查锁定
关于资源加载和性能:
饿汉式在类创建的同时就会实例化一个静态对象,之后不管用不用这个单例都会占据一定的内存,但相应的,第一次调用时速度会很快。
而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。
下面是一个双重检查锁定懒汉式单例模式例子:
1 package singel; 2 3 /* 4 * 单例模式举例说明 5 * 6 */ 7 public class TestMain { 8 public static void main(String[] args) { 9 SingelModel s1 = SingelModel.getSingel(); 10 s1.setAge(10); 11 SingelModel s2 = SingelModel.getSingel(); 12 s2.setAge(20); 13 14 s1.printinfo(); 15 s2.printinfo(); 16 17 System.out.println(s1==s2); 18 } 19 } 20 21 class SingelModel { 22 int age; 23 private static SingelModel singelmodel = null; 24 25 private SingelModel() { 26 } 27 28 public static SingelModel getSingel() { 29 if (singelmodel == null) { 30 synchronized (SingelModel.class) { 31 if (singelmodel == null) { 32 singelmodel = new SingelModel(); 33 } 34 } 35 } 36 return singelmodel; 37 } 38 39 public int getAge() { 40 return age; 41 } 42 43 public void setAge(int age) { 44 this.age = age; 45 } 46 47 public void printinfo() { 48 System.out.println("age:" + age); 49 } 50 }
运行结果:
1 age:20
2 age:20
3 true