java设计模式之单列模式

今天我们就来讲讲单列模式

何为单列模式:

(1):单列类只有一个实例

 (2):共享资源,全局使用

 (3):节省创建时间,提高性能

 说白了就是保证单个jvm中只有一个实列

 不过任何东西都是一把双刃剑,有优秀的地方,就有不足的地方:

单列可能存在线程不安全的问题。(这个后续在考虑)

来:我们用代码演示一下单列模式

public class Singlenton {
     //定义一个私有的静态对象
      private static Singlenton singlenton = new Singlenton();

      //定义私有构造方法
      private Singlenton(){}

      /**
       * 定有公共方法返回该对象的实列
       *
       *
       */
      public static Singlenton getInstance(){
          return singlenton;
      }

  }

我们来总结一下饿汉式的优缺点:

  优点:先天性线程安全,为什么先天性了,因为当类加载的时候,就被创建该对象。

  缺点:如果项目使用过多的饿汉式会产生问题

(1)项目在启动的时候会变的非常慢,存放在方法区占用内存比较大

(2)如果用户不使用该对象的时候,也会被提前创建好,造成内存的浪费。

/*
    单列模式之懒汉式
   */
public class Singlenton {

    private static Singlenton singlenton;

    //定义私有构造
     private Singlenton(){}

     public static Singlenton getSinglenton(){
         //当第一次singlenton等于null时,才会被初始化
         if(singlenton == null){
               singlenton = new Singlenton();     
         }
         //不等于null,直接返回
         return singlenton;
      }
   }

我们来总结一下懒汉式的优缺点:

 优点:当真正需要使用该对象的时候才会被加载,被初始化,提高了性能

 缺点:线程安全问题,在多线程情况下,可能会被初始化多次

哎呀,这个线程安全问题还是挺严重的,有问题不是目的,目的是怎么解决它,这才是问题,废话不多说

第一种方案,在会出现线程安全问题的代码前加上synchronized关键字,

 
 

 那么,这样问题又来了,虽然线程安全的问题是解决了,但是程序执行效率明显下降了

我们必须从源头抓起,比如为什么会产生线程安全问题:当多个线程共享同一个数据,做“写”的操作的时候可能会出现线程安全问题,读是不存在线程安全问题的。

那么我们想想,懒汉式解决线程安全问题为什么效率比较低了,确实因为同步,读和写都加上了锁。

如图所示:当第一次singlenton等于null时,才会被初始化,创建对象,而第一次创建对象的时候才会加锁,之后获取该对象的时候不需要加锁。

那么明白了这些之后,我们就来使用最优的解决方案:双重检验锁   解决懒汉式读和写都加上锁的问题

读的时候不加锁,写的时候才会加锁。

public class Singlenton {

    private static Singlenton singlenton;

    //定义私有构造
     private Singlenton(){}

     public  static Singlenton getSinglenton(){
         //当第一次singlenton等于null时,才会被初始化,才能去创建对象才会加锁,保证线程安全问题
         if(singlenton == null){
              synchronized (Singlenton.class){
                  //当前线程已经获取到锁,在判断一下该对象是否已经初始化过,没有初始化的,进行创建
                  if(singlenton == null){
                         singlenton = new Singlenton();
                  }
              }
         }
         //不等于null,直接返回
         return singlenton;
      }

   }

但是我觉得还是不够好,毕竟加了锁,如何解决读和写都不加锁,还能保证唯一性。

当然有,静态内部类形式

代码演示一遍:
 

/*
    单列模式之静态内部类
   */
public class Singlenton {

      public static Singlenton getInstance(){
          return SinglentonUtils.singlenton;
      }

      //在类里面嵌套的静态类
      private static class SinglentonUtils{
          private static final Singlenton singlenton = new Singlenton();
      }
      
   }

这种单列模式是最简单的,首先静态内部类特征:继承懒汉式优点,同时了也解决了双重检验锁第一次加载慢的问题,读和写都不需要同步,效率非常高。

发布了26 篇原创文章 · 获赞 6 · 访问量 706

猜你喜欢

转载自blog.csdn.net/sdgames/article/details/104122114