标签:带来 线程安全 his blog 内存模型 nal class 枚举类 函数
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 件事情。
但是在 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("这是一个季节"); } }
标签:带来 线程安全 his blog 内存模型 nal class 枚举类 函数
原文地址:http://www.cnblogs.com/holybell/p/6708014.html