java设计模式-单例模式

单例模式:饿汉模式以及懒模式

饿汉模式:线程安全,不会产生多个实例。但如果加载耗时,增加项目初始化时间,如果在运行过程中,没有用到,可能增加空间的浪费

懒汉模式:充分利用资源,实现懒加载策略。(可能线程不安全,需要用户自己优化)


例子

饿汉模式

/**
 * Description:饿汉模式
 * User: lc
 * Date: 2017/9/30 0030
 * Time: 下午 3:52
 */
public class HungrySingleton {
    /**
     * 利用classLoader加载
     */
    private static final HungrySingleton hungrySingleton = new HungrySingleton();

    /**
     * 私有的构造函数:不让外界创建
     */
    private HungrySingleton() {
    }
//提供唯一对外,反射除外
    public static HungrySingleton getInstance() {
        return hungrySingleton;
    }
}

懒汉模式:几种变形


1.不加任何修饰(不安全

/**
 * Description:懒汉模式
 * User: lc
 * Date: 2017/9/30 0030
 * Time: 下午 3:58
 */
public class LazySingleton {
    /**
     * 未初始化
     */
    private static LazySingleton instance;

    private LazySingleton() {

    }

    public static LazySingleton getInstance() {
        //第一次调用会初始化.不过多线程情况下,会重复初始化(线程安全问题)
        if (instance == null) instance = new LazySingleton();
        return instance;
    }
}


2.synchronized(不安全

/**
 * Description:懒汉模式
 * User: lc
 * Date: 2017/9/30 0030
 * Time: 下午 3:58
 */
public class LazySingleton1 {
    /**
     * 未初始化
     */
    private static LazySingleton1 instance;

    private LazySingleton1() {

    }

    public static LazySingleton1 getInstance() {

        if (instance == null) {
            //但是如果线程A和B同时执行到了Synchronized(singleton.class),
            // 虽然也是只有一个线程能够执行,假如线程B先执行,线程B获得锁,线程B执行完之后,线程A获得锁,
            // 但是此时没有检查singleton是否为空就直接执行了,所以还会出现两个singleton实例的情况
            synchronized(LazySingleton1.class)
            {
                instance = new LazySingleton1();
            }

        }
        return instance;
    }
}

2. synchronized以及判断是否NULL( 不安全

/**
 * Description:懒汉模式:双重检查
 * User: lc
 * Date: 2017/9/30 0030
 * Time: 下午 3:58
 */
public class LazySingleton2 {
    /**
     * 要volatile修饰
     * 理由:比如2个线程A/B线程。
     */
    private  static LazySingleton2 instance;

    private LazySingleton2() {

    }

    public static LazySingleton2 getInstance() {

        if (instance == null) {
            synchronized (LazySingleton2.class) {

                if(instance == null)
                    //此处还是有问题:虽然做了双重判断。 因为 newLazySingleTon1()是非原子操作
                    //  A a=new A()
                    //  进行了三步操作:1.申请空间2.将引用指向该空间地址3.初始化构造
                    //在理想情况下,按照1->3->2的步骤执行时,双检锁形式可以正常工作,但是由于Java内存模型,允许重排序,所以
                    //完全可能按照1->2->3的顺序执行,则导致双检锁形式出现问题。即线程1在执行single=new Singleton()语句时,刚好按照1->2->3的顺序                     //执行到step2处,此时,instance指向mem内存区域,而该内存区域未被初始化;同时,线程2在第一个if(instance==null)地方发现instan                     // ce不为null了,于是得到这个为被初始化的实例instance进行使用,导致错误。
                    //synchronized:允许修饰的对象,可见性,但是可以允许jvm的进行重排序
                    instance = new LazySingleton2();
                return instance;
            }

        }
        return instance;
    }
}




3.加synchronized以及volatile(安全)

/**
 * Description:懒汉模式:双重检查
 * User: lc
 * Date: 2017/9/30 0030
 * Time: 下午 3:58
 */
public class LazySingleton2 {
    /**
     * 要volatile修饰
     * 理由:比如2个线程A/B线程。
     */
    private volatile static LazySingleton2 instance;

    private LazySingleton2() {

    }

    public static LazySingleton2 getInstance() {

        if (instance == null) {
            synchronized (LazySingleton2.class) {
                if (instance == null)
                    instance = new LazySingleton2();
            }

        }
        return instance;
    }
}




4.静态内部类(安全)

/**
 * Description:懒汉模式:
 * User: lc
 * Date: 2017/9/30 0030
 * Time: 下午 3:58
 */
public class StaticLazySingleton {
    /**
     *
     *1.私有内部类,外部不知道该类的存在
     * 2.外部类初始化的时候,该内部类还没加载,只有通过第一次调用才(比如这个例子:触发getInstance())加载,加载是利用jvm加载,而jvm加载某个类,只能加载一次,所以是只能有一个class类。故线程安全
     * 3.对外提供唯一的出口
     *
     */
    private StaticLazySingleton() {

    }
   // 静态内部类
    private static class StaticLazySingletonInstance

    {
        private static final StaticLazySingleton staticLazySingleton = new StaticLazySingleton();
    }

    public static StaticLazySingleton getInstance() {


        return StaticLazySingletonInstance.staticLazySingleton;
    }
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值