public class Singleton { private static Singleton instance; //私有静态自身类属性,因为静态方法只能访问静态成员,所以是静态的 private Singleton (){} //私有构造器 public static Singleton getInstance() { //给外界提供单例类对象的静态函数函数:因为使用第一次从单例类中获取单例对象的时候,没有初始化当前类对象,所以只能经过类调用静态方法的形式 if (instance == null) { instance = new Singleton(); } return instance; } }
public class Singleton { private static Singleton instance; //私有静态自身类属性,因为静态方法只能访问静态成员,所以是静态的 private Singleton (){} //私有构造器 public static synchronized Singleton getInstance() { //给外界提供单例类对象的静态函数函数:因为使用第一次从单例类中获取单例对象的时候,没有初始化当前类对象,所以只能经过类调用静态方法的形式 if (instance == null) { instance = new Singleton(); } return instance; } }
public class Singleton { private static Singleton instance; //私有静态自身类属性,因为静态方法只能访问静态成员,所以是静态的 private Singleton (){} //私有构造器 public static synchronized Singleton getInstance() { //给外界提供单例类对象的静态函数函数:因为使用第一次从单例类中获取单例对象的时候,没有初始化当前类对象,所以只能经过类调用静态方法的形式 if (instance == null) { //Single Checked synchronized (Singleton.class) { if (instance == null) { //Double Checked 第二次检查的缘由:有可能多个线程同时经过了第一个检查,可是遇到了同步操做,其中一个线程获取了操做权,所以必须再一次判断,不然后面的线程会再次建立一个对象 instance = new Singleton(); } } } return instance ; } }
这段代码看起来很完美,很惋惜,它是有问题。主要在于instance = new Singleton()这句,这并不是是一个原子操做,事实上在 JVM 中这句话大概作了下面 3 件事情。spring
可是在 JVM 的即时编译器中存在指令重排序的优化。也就是说上面的第二步和第三步的顺序是不能保证的,最终的执行顺序多是 1-2-3 也多是 1-3-2。若是是后者,则在 3 执行完毕、2 未执行以前,被线程二抢占了,这时 instance 已是非 null 了(但却没有初始化),因此线程二会直接返回 instance,而后使用,而后瓜熟蒂落地报错。安全
public class Singleton { private volatile static Singleton instance; //声明成 volatile private Singleton (){} public static Singleton getSingleton() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
public class Singleton{ //类加载时就初始化 private static final Singleton instance = new Singleton(); //使用final关键字保证instance对象只能初始化一次,其后不变 private Singleton(){} public static Singleton getInstance(){ return 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; } }
public enum EasySingleton{ INSTANCE; //默认是使用public static final修饰 }
class Season{ //1.提供类的属性,声明为private final private final String seasonName; private final String seasonDesc; //2.声明为final的属性,在构造器中初始化。 private Season(String seasonName,String seasonDesc){ this.seasonName = seasonName; this.seasonDesc = seasonDesc; } //3.经过公共的方法来调用属性 public String getSeasonName() { return seasonName; } public String getSeasonDesc() { return seasonDesc; } //4.建立枚举类的对象:将类的对象声明public static final public static final Season SPRING = new Season("spring", "春暖花开"); //若是只有一个对象,那么这个类就是一种单例模式的实现,和相似饿汉式,使用静态本类属性,一加载当前类就初始化,不一样的是经过类名获取单一实例 public static final Season SUMMER = new Season("summer", "夏日炎炎"); public static final Season AUTUMN = new Season("autumn", "秋高气爽"); public static final Season WINTER = new Season("winter", "白雪皑皑"); @Override public String toString() { return "Season [seasonName=" + seasonName + ", seasonDesc=" + seasonDesc + "]"; } public void show(){ System.out.println("这是一个季节"); } }