世界上并没有完美的程序,但我们并不因此而沮丧,因为写程序本来就是一个不断追求完美的过程。 ——摘自周志明

(4)单例模式--创建型

多种实现方式

  • 饿汉式
  • 懒汉式 (DCL必会)
  • 枚举 (自己用推荐)
    在多种实现方式下,需要注意多线程环境下线程安全问题

首先,考虑如何确保单例?

1、如果在外部所有人都可以访问单例类的构造器,那就可以直接创建对象,所以构造器私有化。
2、构造器私有化了以后,只有自己可以创建对象,因此需要对外暴露一个方法getInstance(静态方法?原因外部没有实例,没有办法调用对象方法),让其他人获取对象。
3、由于全局唯一,不能创建多次,所以第一次创建完,需要保存到属性中,当下一次获取对象时,先去判断有没有该实例,有则直接返回该实例对象;并且由于getInstance
要访问该属性,所以属性加static进行修饰。原因:静态方法不能访问非静态属性,但是非静态方法可以访问静态属性。有类不一定有对象,有对象时,一定有类。

饿汉式(加载类时直接创建,懒汉式使用时才会创建)

线程安全,原因:类加载时属性初始化,且初始化一次。

public class Singleton {  
   private static Singleton instance = new Singleton();  
   private Singleton (){}  
   public static Singleton getInstance() {  
     return instance;  
   }  
}

懒汉式

非线程安全

public class Singleton {

  private static Singleton singleton;

  private Singleton() {
  }

  public static Singleton getInstance() {
   if (singleton == null) {
    singleton = new Singleton();
   }
   return singleton;
  }
}

线程安全

//同步方法
public class Singleton {  
   private static Singleton instance;  
   private Singleton (){}  
   public static synchronized Singleton getInstance() {  
   if (instance == null) {  
       instance = new Singleton();  
   }  
   return instance;  
   }  
}

//DCL 双检锁
public class Singleton {
    // volatile 防止指令重排,
    private volatile static Singleton singleton;

    private Singleton() {
    }

    // DCL  双检锁
    public static Singleton getSingleton(){
        if(singleton == null){
            synchronized (Singleton.class){
                if (singleton == null){
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

// 枚举方式
public enum Singleton {  
   INSTANCE; 
}
posted @ 2020-07-04 16:38  白杯与咖啡  阅读(133)  评论(0编辑  收藏  举报