单例设计模式

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

核心代码:构造方法私有化,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) 判断是为空,然后进入同步代码中,这是如果不进行判断,则会进入对象创建的逻辑

 

 


 

 

 

posted @ 2020-05-12 17:11  beppezhang  阅读(152)  评论(0编辑  收藏  举报