单例设计模式

来源:互联网 发布:淘宝老客户怎么维护 编辑:程序博客网 时间:2024/05/01 14:47

         其实很早之前就明白了单例,但是因为在大学的时候课程设计都用不到单例,所以仅仅是知道单例,并没有仔细地思考过它的用途。今天是16年11月30号,今天因为项目需要需要写一个单例。在自己需要用单例的时候,为了程序的性能,自然要选择最优的单例。下面就各种单例说一说它们的优缺点。

      1 懒汉模式

       public class Singleton{

              private static Singleton instance;

              private Singleton(){}

              public static Singleton getInstance(){

              if(instance==null){

              instance =  new Singleton();

               }

             return instance;

               }

    }

     这种方式的缺点很明显,就是线程不安全,当同时访问这个单例时,在创建单例的期间有人访问这个单例就又会创造一个实例,造成错误。

   2 懒汉模式改进版

     public class Singleton{

            private static Singleton instance;

            private Singleton(){}

            public static synchronized Singleton getInstance(){

            if(instance==null){

           instance = new Singleton();

           }

           return instance;

           } 

}

    这种方式线程上虽然安全,但是因为实际只有很小一部分情况需要用到锁,加锁降低了效率。所以这个方法也是不好的,线程虽然安全了,但是效率很低。

  3 恶汉模式

   public class Singleton{

          private Singleton instance = new Singleton();

          private Singleton(){}

         public static Singleton getInstance(){

         return instance;

         }

  }

      这种方式的优缺点也很明显,优点是线程安全的,但是却浪费空间。在不使用这个类的时候就实例化了这个类。当然有很多情况这个方式是不错的,比如随着程序的启动就 要实例化的单例。今天就碰到了这种需求,但是我还是选择了最优的单例方式。

  4 双重检测模式

   public class Singleton{

        private Singleton instance;

        private Singleton(){}

        public static Singleton getInstance(){

       if(instance==null){

       synchronized(Singleton.class){

      if(instance==null){

      instance = new Singleton()

      }

      }

      }

    return instance;

       }

 }

这里说一下为什么要双重检测,因为第一次判断为空的时候,在给.class文件加锁之前可能这个类已经被实例化了,所以需要再判断一次。这里说一下如果对方法加锁是线程

安全的,但是效率不好,因为一时间只有一个线程可以调用这个方法。现在是给.class文件加锁,也就是说如果这个类已经实例化了,就可以直接调用了,唯一产生竞争的瞬间就是在实例化第一次的时候。

5 静态内部类

 public class Singleton{

      private Singleton();

      private static class LazyHolder{

     private static final instance =  new Singleton();

     }

     public static Singleton getInstance(){

     return LazyHolder.instance;

    }

  }

    这是我目前使用的方式,巧妙地利用了静态内部类的特点,即只有外部类加载的时候才会产生,所以这种方式不仅线程安全而且没有用锁。


1 0