zoukankan      html  css  js  c++  java
  • 单例模式

    定义

    单例模式即一个 JVM 内存中只存在一个类的对象实例。

    分类

    1. 饿汉式指的是jvm加载类时就创建对象实例,调用效率高,不能延迟加载,影响系统性能,线程安全。具体代码如下:
      /**
       * 饿汉式单例模式:类加载的时候就创建实例
       * 优点:线程安全,类加载时就创建实例,调用效率高
       * 缺点:不能延迟加载,影响系统性能
       */
      public class EagerSingleton {
      /*    //jvm加载类时,就创建实例
          private static EagerSingleton singleton = new EagerSingleton();
          */
      
          private static EagerSingleton singleton=null;
          //在静态代码块中,创建实例,静态块与类同时被jvm加载的
          static {
              singleton = new EagerSingleton();
              //私有构造方法
          }
          private EagerSingleton(){}
      
          //提供一个静态方法给外部调用,获取该单例实例
          public static EagerSingleton getInstance(){
              return singleton;
          }
      
      }
    2. 懒汉式:需要使用实例对象才去创建对象,懒汉式又分二种,线程安全懒汉式,线程不安全懒汉式  线程不安全懒汉式特点:能延迟加载,线程不安全,线程安全懒汉式特点:延迟加载,线程安全,调用效率高。具体代码如下: 
      /**
       * 懒汉式单例模式:使用时才创建实例
       * 分线程安全单例模式,线程不安全单例模式
       * 线程安全懒汉式:
       * 优点:延迟加载,线程安全,
       * 缺点:执行效率低。
       * 线程不安全懒汉式:
       * 优点:延迟加载,
       * 缺点:线程安全
       */
      public class LazySingleton {
      
          private static LazySingleton singleton;
          //私有构造方法
          private LazySingleton(){}
          //1.线程不安全的的懒汉式单例,提供一个非同步的方法,给外部使用者调用,不推荐使用
          /*public static LazySingleton getInstance(){
              if(singleton==null){
                  singleton=new LazySingleton();
              }
              return singleton;
          }*/
          //2.线程不安全的的懒汉式单例同步块,只是单检验锁,依然可能创建多个实例
         /* public static LazySingleton getInstance(){
              if(singleton==null){
                  synchronized (LazySingleton.class){
                      singleton=new LazySingleton();
                  }
      
              }
              return singleton;
          }*/
          // 线程安全的懒汉式:为了解决线程安全,提供一个同步静态方法,给外部使用者调用,但是调用效率低下
          public static synchronized LazySingleton getInstance(){
              if(singleton==null){
                  singleton=new LazySingleton();
              }
              return singleton;
          }
      
      
      
      }
    3. 静态内部类单例模式:在静态内部类中创建外部类的实例,能延迟加载,调用效率高,线程安全,具体代码如下:   

      /**
       * 静态内部类单例模式
       * 特点:线程安全,延迟加载,调用效率高,推荐使用
       */
      public class InnerClassInstance {
          //私有的构造
          private InnerClassInstance(){}
          
          //在静态内部类内创建外部类实例。
           private static class InnerSingleton{
               private static final  InnerClassInstance SINGLETON=new InnerClassInstance();
          }
      
          //对外提供一个静态方法,获取该类的实例
          public static final InnerClassInstance getInstance(){
              return InnerSingleton.SINGLETON;
          }
      
      }


    4. 双重检验锁单例模式:实例变量用volatile进行锁定,保证不同线程对实例变量是可见的,再用同步代码块保证创建的实例是单例,是线程安全的,能延迟加载,调用效率比安全的懒汉式单例模式高

      **
       * 双重检验锁单例模式:实例变量用volatile进行锁定,保证不同线程对实例变量是可见的,再用同步代码块保证创建的实例是单例,可以推荐使用
       * 优点:线程安全,可延迟加载
       * 缺点:调用效率不是很高,但比饿汉式同步方法进行锁定的效率要高。
       */
      public class DoubleLockSingleton {
          //volatile修饰实例,1:使得不同线程对该实例是可见的,禁止进行指令重排序
          private static volatile  DoubleLockSingleton singleton;
          //私有的构造方法
          private DoubleLockSingleton(){}
          //对外提供一个获取该单例的方法
          public static DoubleLockSingleton getInstance(){
              if(singleton==null){
                  synchronized(DoubleLockSingleton.class){
                      if(singleton==null){
                          singleton=new DoubleLockSingleton();
                      }
                  }
              }
              return  singleton;
          }
      
      }
    5.  枚举单例模式:枚举常量是就是枚举类型的一个实例,枚举是天然的单例,代码如下:

      /**
       * 枚举单例,枚举类型是天然的单例,一个成员变量就是枚举的一个实例
       */
      public enum  EnumSingleton {
          SINGLETON;
      }

    使用场景 

    1. 工具类对象
    2. 只需要一个对象的类
    3. 创建频繁经常用到的对象

    jdk单例的应用 

    1. Runntime类

      public class Runtime {
          private static Runtime currentRuntime = new Runtime();
      
          /**
           * Returns the runtime object associated with the current Java application.
           * Most of the methods of class <code>Runtime</code> are instance
           * methods and must be invoked with respect to the current runtime object.
           *
           * @return  the <code>Runtime</code> object associated with the current
           *          Java application.
           */
          public static Runtime getRuntime() {
              return currentRuntime;
          }
    2. Spring容器内的实例默认是饿汉式单例,即容器启动时就实例化bean到容器,通过defalut-lazy-init="true"设置懒汉式实例化bean,使用到bean,才实例化bean,这就是容器化单例。
  • 相关阅读:
    jbox使用总结
    NOI 2012 【迷失游乐园】
    SCOI 2008 【奖励关】
    trie树——【吴传之火烧连营】
    状压DP——【蜀传之单刀赴会】
    NOIP提高组2016 D2T3 【愤怒的小鸟】
    NOIP提高组2013 D2T3 【华容道】
    [学习笔记] [KMP]字符串匹配算法
    SHOI 2014 【概率充电器】
    HNOI 2015 【亚瑟王】
  • 原文地址:https://www.cnblogs.com/shareAndStudy/p/12728187.html
Copyright © 2011-2022 走看看