zoukankan      html  css  js  c++  java
  • 单例模式总结

    昨天翻了本设计模式的书,发现单例模式竟然有点弄不明白了,抓紧查资料补上,这里总结下。

    1:

    class Singleton
    {
    private static Singleton instance;
    private Singleton()
    {
    //
    }

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

    注意:构造函数私有,方法静态

    问题:无法保证线程安全,有多个线程访问getInstance方法的时候可能产生多个Singleton对象。

    2:

    可以给getInstance方法添加同步:

    public static synchronized Singleton getInstance()
    {
    if (instance == null) //1
    instance = new Singleton(); //2
    return instance; //3
    }

    这样能满足需求,但是会带来性能上的损失。一般同步的方法比非同步的方法效率要低上百倍

    3:

    然后是懒汉式的单例模式:

    class Singleton
    {
    private static Singleton instance = new Singleton();
    private Singleton()
    {
    //
    }

    public static Singleton getInstance()
    {
    return instance;
    }
    }

    这种方法能保证instance实例在Singleton类第一次加载的时候初始化,解决了同步问题

    进一步的要求可能是不想让instance对象在类加载的时候初始化,而在使用getInstance方法的时候才初始化

    4:

    双重锁

    public static Singleton getInstance()
    {
    if (instance == null)
    {
    synchronized(Singleton.class) { //1
    if (instance == null) //2
    instance = new Singleton(); //3
    }
    }
    return instance;
    }

    这种方法能保证instance只被初始化一次。但是由于JVM内部的问题,该方法还是有漏洞的。

    假设线程1进入到步骤2,执行步骤3未完成,会先将instance设为非null值。

    这时候线程2会在判断instance==null的时候失败,返回一个不完整的intance对象

    5:

    既要lazy loading,又要同步~

    Bob Lee提出了一种方法:

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

    在该方法中,Singleton有一个静态内部类,内部类在外部类加载的时候并不会加载,只有在调用getInstance方法的时候加载SingletonHolder类。

    如上面的程序还是可能有问题:

    Singleton.SingletonHolder sh = new Singleton.SingletonHolder();
    Singleton instance
    = Singleton.SingletonHolder.instance;
    instance
    = sh.instance;

    上面的代码是可以访问SingletonHolder的内容的~~

    所以进一步的把SingletonHolder设为private的应该会更好。

    所以最后的代码如下:

    public class Singleton {
    private Singleton(){
    }
    private static class SingletonHolder {
    static Singleton instance = new Singleton();
    }
    public static Singleton getInstance() {
    return SingletonHolder.instance;
    }
    public static void main(String [] args)
    {
    Singleton.getInstance();
    }
    }

  • 相关阅读:
    crontab定时任务
    find at tar命令详解
    c#调用c++dll库调用约定问题
    ATL和ActiveX做的控件.dll和.ocx最主要的区别(摘录)
    实现内外网的策略
    探查“ORA-01000:超出最多允许打开的游标数”
    良好编程习惯的重要性
    PCS不能用问题
    msf外网--->>安卓
    github 克隆代码问题
  • 原文地址:https://www.cnblogs.com/macula7/p/2003225.html
Copyright © 2011-2022 走看看