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

    C++单例模式

    单例饿汉式

    • 加载类的时候初始化(不使用也会构造类,空间换时间)
    #include <stdio.h>
    #include <string>
    
    class DriverManger
    {
    private:
      long m_nDate;
      int m_nDriverNum;
      std::string m_strDriverInfo;
    
    private:
      // 私有构造函数,禁止new方式实例化
      DriverManger(){printf("new DriverManger.. 
    ");}
    
      // 私有析构,实例的生命周期是程序开始到结束,无需手动释放
      ~DriverManger(){printf("delete DriverManger.. 
    ");}
    
      // 禁止拷贝构造和赋值操作符
      DriverManger(DriverManger&)/*=delete*/;
      const DriverManger& operator=(const DriverManger&)/*=delete*/;
    
      static DriverManger instance;
    
    public:
      static DriverManger& GetInstance(void)
      {
        return instance;
      }
    };
    
    //下面这个静态成员变量在类加载的时候就已经初始化好了
    DriverManger DriverManger::instance;
    
    int main(void)
    {
      printf("begin main.. 
    ");
      DriverManger& driver1 = DriverManger::GetInstance();
      DriverManger& driver2 = DriverManger::GetInstance();
    
      printf("%p && %p",&driver1, &driver2);
    
      return 0;
    }
    

    单例懒汉式

    • 使用到时(调用getInstance方法)才构造类实例
    • 多线程造成的实例不唯一
    #include <stdio.h>
    #include <string>
    
    class DriverManger
    {
    private:
      long m_nDate;
      int m_nDriverNum;
      std::string m_strDriverInfo;
      static DriverManger* theDriver;
    
    private:
      // 私有构造函数,禁止new方式实例化
      DriverManger(){}
    
      // 禁止拷贝构造和赋值操作符
      DriverManger(DriverManger&)/*=delete*/;
      const DriverManger& operator=(const DriverManger&)/*=delete*/;
    
    public:
      static DriverManger* GetInstance(void)
      {
        if (nullptr == theDriver)
        {
          theDriver = new DriverManger();
        }
    
        return theDriver;
      }
    
      ~DriverManger()
      {
        if (nullptr != theDriver)
        {
          delete theDriver;
        }
      }
    };
    
    DriverManger* DriverManger::theDriver = nullptr;
    
    int main(void)
    {
      DriverManger* pDriver = DriverManger::GetInstance();
      DriverManger* pDriver2 = DriverManger::GetInstance();
      printf("%p && %p 
    ", pDriver, pDriver2);
    
      getchar();
    
      return 0;
    }
    

    局部静态变量的单例懒汉式

    • 使用局部静态变量的特性保证了线程安全
    #include <stdio.h>
    #include <string>
    
    class DriverManger
    {
    private:
      long m_nDate;
      int m_nDriverNum;
      std::string m_strDriverInfo;
    
    private:
      // 私有构造函数,禁止new方式实例化
      DriverManger(){}
    
      // 禁止拷贝构造和赋值操作符
      DriverManger(DriverManger&)/*=delete*/;
      const DriverManger& operator=(const DriverManger&)/*=delete*/;
    
    public:
      static DriverManger& GetInstance(void)
      {
        // 静态局部变量保证每次获取到唯一实例
        static DriverManger driver;
        return driver;
      }
    
      ~DriverManger(){}
    };
    
    int main(void)
    {
      DriverManger& driver1 = DriverManger::GetInstance();
      DriverManger& driver2 = DriverManger::GetInstance();
    
      return 0;
    }
    

    JAVA单例模式

    单例饿汉式

    缺点是加载类就分配空间,浪费资源

    • 构造器私有
    • 提供外界可访问方法
    public class Student {
    	// 构造私有,外界不能直接创建
    	private Student() {
    	}
    
    	// 类本身创建一个对象
    	//private外界不能干预对象的赋值
    	//static静态方法调用静态成员
    	private static Student s = new Student();
    
    	// 提供外界访问该对象的方法
    	//static静态外界可以直接通过类名访问
    	public static Student getStudent() {
    		return s;
    	}
    	
    	public void show(){
    		System.out.println("hello");
    	}
    
    }
    

    单例懒汉式(方法锁保证线程安全)

    • 效率低
    public class Teacher {
    	private Teacher(){	
    	}
    	
    	private static Teacher t = null;
    	
    	//同步方法保证线程安全,因为有可能多个线程同时进入判断语句中
    	public synchronized static Teacher getTeacher(){
    		if(t==null){
    			t = new Teacher();
    		}
    		return t;
    	}
    }
    

    双重检测的懒汉式

    /**
     * 线程安全的单例懒汉式
     */
    public class ConcurrentSingle {
        private ConcurrentSingle(){
    
        }
    
        // volatile防止 new 时的指令重排
        private volatile static ConcurrentSingle theApp;
    
        // 双重检测锁
        public static ConcurrentSingle getTheApp() {
            if (theApp == null) {
                synchronized (ConcurrentSingle.class) {
                    if (theApp == null) {
                        theApp = new ConcurrentSingle(); // 可能指令重排
                    }
                }
            }
            return theApp;
        }
    }
    

    静态内部类单例模式

    public class InnerSingle {
        private InnerSingle() {
    
        }
    
        public InnerSingle getInstance() {
            return Inner.HOLDER;
        }
    
        // 静态内部类
        private static class Inner{
            // 外部类的实例化对象
            private static final InnerSingle HOLDER = new InnerSingle();
        }
    }
    

    枚举实现单例

    • 线程安全
    • 可防止反射破坏
    public enum EnumSingle {
        INSTANCE;
        private Resource resource;
    
        EnumSingle() {
            resource = new Resource();
        }
    
        public Resource getResource() {
            return resource;
        }
    }
    
    class Resource{
    
    }
    

    jdk中使用的单列模式

        Runtime r = Runtime.getRuntime();
    

    源码

    public class Runtime {
        private static Runtime currentRuntime = new Runtime();
        public static Runtime getRuntime() {
            return currentRuntime;
        }
    ...
    
  • 相关阅读:
    kafka 学习资料
    kafka 的 docker 镜像使用
    SpringBoot 使用 Mybatis 注解进行一对多和多对多查询(不推荐使用注解方式)
    MYSQL 中的 int(11) 到底代表什么意思?
    MyBatis 学习资料
    什么是 CAP 理论?
    一致性哈希算法原理
    SELECT 语句语法
    MySQL中如何实现 select top n
    基于 debian:stretch-slim 系统镜像的 docker 镜像,安装 curl
  • 原文地址:https://www.cnblogs.com/xiongyungang/p/13098582.html
Copyright © 2011-2022 走看看