单例模式

来源:互联网 发布:手机office软件下载 编辑:程序博客网 时间:2024/05/21 11:02
//懒汉式单例类.在第一次调用的时候实例化自己   public class Singleton {      private Singleton() {}      private static Singleton single=null;      //静态工厂方法       public static Singleton getInstance() {           if (single == null) {                 single = new Singleton();           }            return single;      }  } 


//饿汉式单例类.在类初始化时,已经自行实例化   public class Singleton1 {      private Singleton1() {}      private static final Singleton1 single = new Singleton1();      //静态工厂方法       public static Singleton1 getInstance() {          return single;      }  }  


两者区别:
1:饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题,

       懒汉式本身是非线程安全的,为了实现线程安全三种方法解决:

1:在getInstance方法上加同步

public static synchronized Singleton getInstance() {           if (single == null) {                 single = new Singleton();           }            return single;  }  
2:双重检查锁定

public static Singleton getInstance() {          if (singleton == null) {                synchronized (Singleton.class) {                   if (singleton == null) {                      singleton = new Singleton();                  }                }            }            return singleton;       } 
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;        }    }    
2:资源加载和性能

饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成,

而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。

至于1、2、3这三种实现又有些区别,

第1种,在方法调用上加了同步,虽然线程安全了,但是每次都要同步,会影响性能,毕竟99%的情况下是不需要同步的,

第2种,在getInstance中做了两次null检查,确保了只有第一次调用单例的时候才会做同步,这样也是线程安全的,同时避免了每次都同步的性能损耗

第3种,利用了classloader的机制来保证初始化instance时只有一个线程,所以也是线程安全的,同时没有性能损耗,所以一般我倾向于使用这一种。

3:应用

懒汉式:

1:保证一个数据库对应一个sessionFactory 
   2:保证同一个客户端用户使用同一个session对象

public class HibernateSessionFactory {private static SessionFactory sessionFactory;// 使用本地线程对象管理session对象private final static ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();// 保证满足第一个条件static {buildSessionFactory();}/** * 定义构建SessionFactory对象的方法 2017年4月14日 *  * @return SessionFactory buildSessionFactory */public static void buildSessionFactory() {// 判断SessionFactory是否为空if (sessionFactory == null) {Configuration cfg = new Configuration().configure();ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(cfg.getProperties()).build();sessionFactory = cfg.buildSessionFactory(serviceRegistry);}}/** * 定义获取session的方法 * 2017年4月14日 * @return * Session * getSession */public static Session getSession() {// 从本地线程中获取Session对象Session session = threadLocal.get();// 判断session为null需要把创建的session对象方法放到本地线程中if (session == null) {// 判断sessionFactory为空if(sessionFactory == null){buildSessionFactory();}session = sessionFactory.openSession();// 设置到本地线程中threadLocal.set(session);}return session;}public static void closeSession(){Session session = threadLocal.get();if(session.isConnected() && session!=null){session.close();session = null;threadLocal.set(null);}}}


jdbc属性文件解析类

public class PropertiesParser extends Properties {private PropertiesParser() {}/** *  */private static final long serialVersionUID = 1L;private static PropertiesParser pp;// 装载属性文件     {try {this.load(this.getClass().getClassLoader().getResourceAsStream("jdbc.properties"));} catch (IOException e) {e.printStackTrace();}}        /**     * 定义创建当前类实例的静态的方法     */    public static PropertiesParser newInstance() {    if (pp == null) {    pp = new PropertiesParser();    }        return pp;    }        /**     * 定义通过属性文件中对应key获取值得方法     */    public String getValueByKey(String key) {    return getProperty(key);    }}






0 0
原创粉丝点击