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

    单例模式,就是只有一个实例,并且自己负责创建自己的对象,对外暴露获取对象的方法,不允许外部实例化该类。

    核心代码:构造方法私有化,private,持有自己类型的属性,对外提供获取实例的静态方法

    1:懒汉模式:

    代码如下:

     1 public class Singleton {  
     2     private static Singleton instance;  
     3     private Singleton (){}  
     4   
     5     public static Singleton getInstance() {  
     6     if (instance == null) {  
     7         instance = new Singleton();  
     8     }  
     9     return instance;  
    10     }  
    11 }

    特点:

    当使用方调用 getInstance() 方法时,对象才进行加载。当多线程调用getInstance() 方法时,产生竞争条件,可能在 instance = new Singleton(); 这段逻辑生成多个对象。造成线程不安全。

    2:饿汉模式:

    代码如下:

    1 public class Singleton {  
    2     private static Singleton instance = new Singleton();  
    3     private Singleton (){}  
    4     public static Singleton getInstance() {  
    5     return instance;  
    6     }  
    7 }

    特点:

    这里 Singleton 使用static 进行修饰,当类通过类加载器进行加载的时候 会执行 static 修饰的变量,被static修饰的变量是随着类的加载而存在,随着类的消失而消失的。

    所这里的instance 变量在Singleton类加载的时候会开始执行   private static Singleton instance = new Singleton(); 这段代码的逻辑。

    所以在全局中只会存在一个实例。这样是线程安全的,只是这种方式不管用到了还是没用到这个实例都会去实例化它,容易产生内存。

    3:双重锁模式

    保证使用到这个对象是采取初始化这个对象,切线程安全:

    代码如下:

     1 public class Singleton {  
     2     private volatile static Singleton singleton;  
     3     private Singleton (){}  
     4     public static Singleton getSingleton() {  
     5     if (singleton == null) {  
     6         synchronized (Singleton.class) {  
     7         if (singleton == null) {  
     8             singleton = new Singleton();  
     9         }  
    10         }  
    11     }  
    12     return singleton;  
    13     }  
    14 }

    这里当用户需要调用 getSingleton()  方法获取对象实例的时候,

    1:判断实例是否存在,如果存在则直接返回对象,提升代码执行效率

    2:判断对象确实不存在的情况下,进行加锁后创建对象,这里再次进行一次判断对象是否存在。对象不存在的情况下创建对象。

    下面对以下几行代码进行分析:

    第二行   第五行   第七行 代码进行分析

    第二行:private volatile static Singleton singleton; 

    这行代码用了 volatile 关键字进行修饰,volatile可以 保证 修饰的变量 可见性 但是不能保证原子性,volatile修饰保证jvm加载代码不会重排序,保证多线程下访问安全。

    当线程已经执行完第8行代码,创建好了对象了,这个时候新的线程执行进入第5行代码进行判断,如果没有volatile 进行修饰的话,这时候该线程中获取的私有变量为null,则会进入同步的创建代码的逻辑。

    使用volatile修饰,可以保证同步到全局变量中获取;

    第五行   if (singleton == null)

    这行代码主要是判断是否存在实例,如果存在直接返回,如果没有这行代码,这接下来直接进入加锁的逻辑,多线程访问的情况下,可以保证线程的安全,但是每个线程都会排队进入同步的方法,导致效率低下。

    第七行  if (singleton == null)

    假设第一个线程进入 singleton = new Singleton(); 创建了对象,其他线程在第一层if (singleton == null) 判断是为空,然后进入同步代码中,这是如果不进行判断,则会进入对象创建的逻辑

    
    
    

     

  • 相关阅读:
    petshop4.0(转)
    分层依据(转)
    如何让一个函数返回多个值
    谁访问过我的电脑
    博客第一帖!
    开发辅助工具大收集
    VC 通过IHTMLINTEFACE 接口实现网页执行自定义js代码
    vi命令大全
    #include <sys/types.h>
    #include <arpa/inet.h>
  • 原文地址:https://www.cnblogs.com/beppezhang/p/12877358.html
Copyright © 2011-2022 走看看