单例模式学习

单例模式实现

一.实现双重校验锁

public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
}  

特点:通过关键字synchronized保证高并发下,初始化对象为单例。缺点性能较差,对象属性需要volatile进行修饰防止编译期间指令重排序,导致返回对象为null。

二.通过类加载机制

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

或

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

特点:饿汉模式,ClassLoader的loadClass方法在加载类的时候使用了synchronized关键字。也正是因为这样, 除非loadClass被重写,这个方法默认在整个装载过程中都是同步的(线程安全的),保证方法调用前已被初始化一次。

三.利用内部类

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

特点:使用静态内部类,借助了classloader来实现了线程安全,这与饿汉模式有着异曲同工之妙,但是他有兼顾了懒汉模式的lazy-loading功能,相比较之下,有很大优势。

四.利用枚举

public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}  

特点:解决通过反序列化导致单例破坏,代码简洁。

五.通过CAS

public class Singleton {
    private static final AtomicReference<Singleton> INSTANCE = new AtomicReference<Singleton>(); 

    private Singleton() {}

    public static Singleton getInstance() {
        for (;;) {
            Singleton singleton = INSTANCE.get();
            if (null != singleton) {
                return singleton;
            }

            singleton = new Singleton();
            if (INSTANCE.compareAndSet(null, singleton)) {
                return singleton;
            }
        }
    }
}

特点:不通过锁的机制。

问题:单例的破坏

public class Test {

    public static void main(String[] args) throws FileNotFoundException,
            ClassNotFoundException {
        // 获取单例对象
        Eagersingleton instance = Eagersingleton.getInstance();

        // 通过反序列化读取对象
        Eagersingleton instance2 = null;
        try {
            ObjectOutputStream oossStream = new ObjectOutputStream(
                    new FileOutputStream("D:/EagersingletonTest.txt"));

            // 通过序列化把对象写到文件中
            oossStream.writeObject(instance);
            oossStream.flush();
            oossStream.close();
            // 读取文件的对象
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
                    "D:/EagersingletonTest.txt"));

            instance2 = (Eagersingleton) ois.readObject();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println(instance);
        System.out.println(instance2);
    }
}
/**
 * @Descrption
 * @ClassName Eagersingleton
 * @Author qiu_lijun
 * @Date 2019/5/23 17:53
 * @Version 1.0
 */
public class Eagersingleton implements Serializable {

    private static final long serialVersionUID = 888L;
    private static Eagersingleton m_instance = new Eagersingleton();// 初始化时已经自行实例化

    // 私有默认构造方法
    private Eagersingleton() {
    }

    // 静态工厂方法
    public static Eagersingleton getInstance() {
        return m_instance;
    }

   /* public Object readResolve() {
        return m_instance;
    }*/
}

在调用readObject方法中,会利用反射回去对象实例。假如为在类中定义readResolve方法,就会返回一个新的对象。导致单例模式被破坏。解决方法重写readResolve方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值