Java程序性能优化 读书笔记(二)设计模式:单例模式

来源:互联网 发布:自学编程的app 编辑:程序博客网 时间:2024/05/21 11:24

转载:Spring的单例模式底层实现


单例模式也属于创建型模式,所谓单例,顾名思义,所指的就是单个实例,也就是说要保证一个类仅有一个实例
单例模式有以下的特点:
① 单例类只能有一个实例
② 单例类必须自己创建自己的唯一实例
③ 单例类必须给所有其他对象提供这一实例

单例模式的好处

1、对于频繁使用的对象,可以省略对象创建的时间

2、由于new操作的次数减少,因而对系统内存的使用频率也会降低,减轻GC压力,缩短GC停顿时间

单例模式主要针对于系统的关键组件和被频繁使用的对象,使用它可以有效改善系统的性能。

单例类必须要有:

1、private访问级别的构造函数,只有这样才能确保单例不会在系统的其他代码内被实例化

2、instance(实例对象)和getInstance()(获取实例对象的方法)方法必须是static


按照单例的实现思路,共有三种方式实现单例

1.饿汉模式

public class Singleton1{        private static final Singleton1 instance=new Singleton1();        //私有的默认构造函数        private Singleton1(){}        //静态工厂方法        public static Singleton1 getInstance(){            return instance;        }    }     

在这个类被加载时,静态变量instance会被初始化,此时该类的私有构造函数被调用,这时候,单例类的唯一实例就被创建出来了
值得注意的是:由于构造函数是私有的,因此该类不能被继承

2. 懒汉模式

public class Singleton2{       private static final Singleton2 instance=null;       //私有的默认构造函数       private Singleton1(){}       //静态工厂方法       public synchronized static Singleton2 getInstance(){         If(instance==null){           Instance=new Singleton2();         }         Return instance;       }    }
这种写法和第一种的区别在于:实例并没有直接实例化,而是在静态工厂方法被调用的时候才进行的,而且对静态工厂方法使用了同步化,以处理多线程并发的环境

饿汉式单例在自己被加载时就将自己实例化,如果从资源利用效率角度来讲,比懒汉式单例类稍差些。但是从速度和反应时间角度来讲,则比懒汉式要稍好些。但是遗憾的是:懒汉式单例类也不能被继承

3. 内部类方式

public class SingleTon03 {      private SingleTon03(){          System.out.println("staticSingle is create");      }      private static class SingleHolder{          private static SingleTon03 instance=new SingleTon03();      }      public static SingleTon03 getInstance(){          return SingleHolder.instance;      }  }  

单例模式使用内部类来维护到单例的实例,当SingleTon3被加载时,其内部类并不会被初始化,因此单例类被加载jvm时,不会初始化单例类,而当getInstance()方法被调用时,才加载SingleHolder(内部类),从而初始化instance。

此种方式实例创建是在类加载时完成,因此天生对多线程友好,getInstance方法不必使用同步关键字,是一种比较完善的实现,但是由于构造函数依然是private,无法被继承。

4. 单例注册表模式

import java.util.HashMap;    public class RegSingleton{        static private HashMap registry=new HashMap();       //静态块,在类被加载时自动执行        static{         RegSingleton rs=new RegSingleton();         Registry.put(rs.getClass().getName(),rs);       }       //受保护的默认构造函数,如果为继承关系,则可以调用,克服了单例类不能为继承的缺点        protected RegSingleton(){}        //静态工厂方法,返回此类的唯一实例        public static RegSingleton getInstance(String name){            if(name==null){              name="RegSingleton";            }if(registry.get(name)==null){                try{                    registry.put(name,Class.forName(name).newInstance());                }catch(Exception ex){                ex.printStackTrace();            }            }            return (RegSingleton)registry.get(name);        }    } 

采用单例注册表方式可以创建可以被继承的单例类,Spring IoC也采用了这种方式生成注入类的单例。


单例类的序列化

一般来说单例类不用于序列化,序列化和反序列化可能会破坏单例,但可以通过重写readReslove的方式加以避免。

public class SingleTon03 {      private SingleTon03(){          System.out.println("staticSingle is create");      }      private static class SingleHolder{          private static SingleTon03 instance=new SingleTon03();      }      public static SingleTon03 getInstance(){          return SingleHolder.instance;      }      private Object readReslove(){        return SingleHolder.instance;    }}  


阅读全文
0 0
原创粉丝点击