欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

单例模式的几种创建方式

程序员文章站 2022-07-14 09:27:39
...

单例模式

创建方式

  • 饿汉方式:指全局的单例实例在类装载时构建
  • 懒汉方式:指全局的单例实例在第一次被使用时构建

不管是那种创建方式,它们通常都存在下面几点相似处:

  • 单例类必须要有一个 private 访问级别的构造函数,只有这样,才能确保单例不会在系统中的其他代码内被实例化;
  • instance 成员变量和 uniqueInstance 方法必须是 static 的。

饿汉模式(线程安全)

public class Singleton {
	//在静态初始化器中创建单例实例,这段代码保证了线程安全
    private static Singleton uniqueInstance = new Singleton();
    //Singleton类只有一个构造方法并且是被private修饰的,所以用户无法通过new方法创建该对象实例
    private Singleton(){}
    public static Singleton getInstance(){
    	return uniqueInstance;
    }
}

懒汉模式

线程不安全

public class Singleton {  
      private static Singleton uniqueInstance;  
      private Singleton () {}   
      //没有加入synchronized关键字的版本是线程不安全的
      public static Singleton getInstance() {
          //判断当前单例是否已经存在,若存在则返回,不存在则再建立单例
	      if (uniqueInstance == null) {  
	          uniqueInstance = new Singleton();  
	      }  
	      return uniqueInstance;  
      }  
 }

线程安全

  1. getInstance方法加上syncronized
public class Singleton {  
      private static Singleton uniqueInstance;  
      private Singleton (){
      }   
      // 加入synchronized关键字的版本是线程安全的
            public static synchronized Singleton getInstance() {  
	      if (instance == null) {  
	          uniqueInstance = new Singleton();  
	      }  
	      return uniqueInstance;  
      }   
 }

双重校验锁版本

  1. 实例变量为volatile
public class Singleton {

    // volatile保证,当uniqueInstance变量被初始化成Singleton实例时,多个线程可以正确处理				   uniqueInstance变量
    private volatile static Singleton uniqueInstance;
    private Singleton() {
    }
    public static Singleton getInstance() {
       //检查实例,如果不存在,就进入同步代码块
        if (uniqueInstance == null) {
            //只有第一次才彻底执行这里的代码
            synchronized(Singleton.class) {
               //进入同步代码块后,再检查一次,如果仍是null,才创建实例
                if (uniqueInstance == null) {
                    uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }
}

懒汉式(登记式/静态内部类方式)

只有通过显式调用 getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 instance(只有第一次使用这个单例的实例的时候才加载,同时不会有线程安全问题)。

public class Singleton {  
    private static class SingletonHolder {  
    	private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
    return SingletonHolder.INSTANCE;  
    }  
} 

饿汉式(枚举方式)

使用枚举来实现单实例控制会更加简洁,而且无偿地提供了序列化机制,并由JVM从根本上提供保障,绝对防止多次实例化,是更简洁、高效、安全的实现单例的方式。

public enum Singleton {
	 //定义一个枚举的元素,它就是 Singleton 的一个实例
    INSTANCE;  
    
    public void doSomeThing() {  
	     System.out.println("枚举方法实现单例");
    }  
}
public class ESTest {

	public static void main(String[] args) {
		Singleton singleton = Singleton.INSTANCE;
		singleton.doSomeThing();//output:枚举方法实现单例

	}
}