Java设计模式--单例模式(代码详解懒汉饿汉模式)

Posted RAIN 7

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java设计模式--单例模式(代码详解懒汉饿汉模式)相关的知识,希望对你有一定的参考价值。

文章目录

设计模式-单例模式

啥是单例模式?

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

1.在类中就创建实例,只创建一个实例

2.类外如果想要调用这个对象必须调用getInstance方法获取实例,好处是减少了创建对象、销毁对象的开销

3.获取实例只能获取到类提供的唯一实例

懒汉模式

解释一下懒汉,懒汉就是懒加载,在类加载的时候不会去创建实例,在第一次调用的时候才会创建实例。

public class Singleton 

/**
* 以下是懒汉模式的代码
*/

    // 会产生线程安全问题,使用双重校验锁来保证安全

    private static Singleton instance = null;
  
   // 类加载过程不创建实例,实例设置为null

    public Singleton() 
    

    public static Singleton getInstance()
    // 第一次调用该类才会创建实例
        if(instance==null)
            return instance = new Singleton();
        
    // 其后每次调用实例都使用上面创建的实例
        return instance;
    


好处: 只有调用资源的时候才会创建实例,所以节约了资源。

坏处:懒汉模式会带来线程安全问题

如果多个线程同时获取实例,都是第一次获取,对执行 if(instance==null) 这个语句中的new实例,所以会创建出多个实例来。


怎么解决线程安全问题?


1.使用双重校验锁

第一个if(instance==null)

先判断实例是否存在,不存在再加锁

第二个if(instance==null)

当多线程都是第一次调用该对象的时候,只有一个线程能够进入,避免创建多个对象

 public static Singleton getInstance()
        if (instance==null)  // 先判断实例是否存在,不存在再加锁
            synchronized (Singleton.class) 
                if(instance==null)// 多线程情况下,只有一个能进入,避免创建多个对象。
                    return instance = new Singleton();
                
            
        
        return instance;
    

2.volatile 修饰实例对象,禁止指令重排序

 private volatile static Singleton instance = null;

Instance = new Singleton 这段代码其实分成三步骤

1.为 new Singleton 分配内存空间

2.初始化对象实例

3.Instance 变量指向这块内存地址

初始化时间有点慢,所以JVM指令重排,顺序变了1->3->2,在单线程的情况下没啥问题,但是如果在多线程的情况下,第一个线程进去了,执行了1-3,这个时候第二个线程一个 实例不为null,直接返回了没有初始化 的实例对象,明显产生了线程安全问题。

所以使用 volatile 禁止指令重排。


线程安全的懒汉模式

public class Singleton 

    /**
 * 以下是懒汉模式的代码
 */

    // 会产生线程安全问题,使用双重校验锁来保证安全,使用volatile禁止指令重排序

    private volatile static Singleton instance = null;

    public Singleton() 
    

    public static Singleton getInstance()
        if (instance==null) 
            synchronized (Singleton.class) 
                if(instance==null)
                    return instance = new Singleton();
                
            
        
        return instance;
    



饿汉模式

理解饿汉,因为太饿了,所以一拿到东西就想吃,这里就是类加载的过程就直接创建唯一实例。

好处:没有线程安全问题

坏处:不像懒汉模式调用才创建实例,这个是类加载就创建实例,所以如果一直没调用,也得创建实例浪费资源。

public class Singleton 
    private static Singleton instance = new Singleton();

    public Singleton() 
    
    // 调用方法获取实例,只有读,所以没有线程安全问题
    public static Singleton getInstance()
        return instance;
    

以上是关于Java设计模式--单例模式(代码详解懒汉饿汉模式)的主要内容,如果未能解决你的问题,请参考以下文章

设计模式之单例模式详解(java)

设计模式之单例模式详解(java)

详解单例模式

java设计模式详解

java设计模式详解

手写单例模式(饿汉和饱汉模式)和工厂模式