设计模式第一课-单例模式(懒汉模式和饿汉模式)

单例模式

个人理解:单例模式实际就是通过类加载的方式获取到一个对象,并且保证这个对象在使用中只有一个,不允许再次被创建

一、懒汉模式

1、懒汉模式的基础写法

代码解释:
(1)、编写LazySingleton类的时候,需要将成员属性设定为static,这样才会是类属性
(2)、重写构造方法,将其设置为private,这样就防止其他人在new这个对象了,防止该类被重复new

package com.example.sheji.singleton.v1;
public class LazySingletonTest {

    public static void main(String[] args) throws Exception {
        LazySingleton instance = LazySingleton.getInstance();
        LazySingleton instance1 = LazySingleton.getInstance();
        System.out.println(instance);
        System.out.println(instance1);
    }
}

class LazySingleton{

    private static LazySingleton instance;

    private LazySingleton(){

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

执行结果:可以看到两个对象是一样的,懒汉模式已经基本实现。
但这样的写法在多线程环境下是有问题的!
在这里插入图片描述
当我们改为多线程的方式执行就会出现问题,对象居然不一样了

public class LazySingletonTest {

    public static void main(String[] args) throws Exception {
        Thread thread1 = new Thread(() -> {
            LazySingleton instance = LazySingleton.getInstance();
            System.out.println(instance);
        });
        Thread thread2 = new Thread(() -> {
            LazySingleton instance = LazySingleton.getInstance();
            System.out.println(instance);
        });
        thread1.start();
        thread2.start();

    }
}

class LazySingleton{
    private static LazySingleton instance;
    private LazySingleton(){

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

在这里插入图片描述
但如果我们让其中一个线程睡眠200ms呢,会发现对象的值又一样了
在这里插入图片描述
原因如下图,在两个线程都没有休眠的时候,因为执行太快,当第一个线程执行到if(instance == null)里面时,对象还没有new出来,第二个线程也执行到了,所以出现了这种情况
当让第二个线程休眠200ms的时候,第一个线程已经初始化好对象了,第二个线程就不需要初始化了
在这里插入图片描述

2、懒汉模式的升级写法

解释:
(1)、加锁synchronized ,当对象为空时,只允许一个线程先执行,其他线程等待,可以保证对象只被初始化一次
(2)、volatile 关键字,是为了防止指令重排序,防止instance 还没有开辟空间时,先被赋值了

class LazySingleton{

    private static volatile LazySingleton instance;

    private LazySingleton(){

    }
    public static LazySingleton getInstance()  {

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

测试结果:
在这里插入图片描述

二、饿汉模式

public class HungrySingletionTest {
    public static void main(String[] args) {
//        HungrySingletion instance1 = HungrySingletion.getInstance();
//        HungrySingletion instance2 = HungrySingletion.getInstance();
//        System.out.println(instance2);
//        System.out.println(instance1);

        Thread thread = new Thread(() -> {
            HungrySingletion instance1 = HungrySingletion.getInstance();
            System.out.println(instance1);
        });
        Thread thread1 = new Thread(() -> {
            HungrySingletion instance2 = HungrySingletion.getInstance();
            System.out.println(instance2);
        });
        thread.start();
        thread1.start();
    }
}
class HungrySingletion{
    private static HungrySingletion instance = new HungrySingletion();
    private HungrySingletion(){
    }
    public static HungrySingletion getInstance() {
        return instance;
    }
}

执行结果:
在这里插入图片描述
解释:因为饿汉模式是在利用jvm在加载过程就已经自动初始化好了,所以不论是否使用多线程,都是一个对象

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

friover

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值