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

单例模式

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

一、懒汉模式

1、懒汉模式的基础写法

代码解释:

(1)、编写LazySingleton类的时候,需要将成员属性设定为static,这样才会是类属性

(2)、重写构造方法,将其设置为private,这样就防止其他人在new这个对象了,防止该类被重复new

java 复制代码
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;
    }
}

执行结果:可以看到两个对象是一样的,懒汉模式已经基本实现。

但这样的写法在多线程环境下是有问题的!

当我们改为多线程的方式执行就会出现问题,对象居然不一样了

java 复制代码
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 还没有开辟空间时,先被赋值了

java 复制代码
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;
    }
}

测试结果:

二、饿汉模式

java 复制代码
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在加载过程就已经自动初始化好了,所以不论是否使用多线程,都是一个对象

相关推荐
vker20 分钟前
第 1 天:单例模式(Singleton Pattern)—— 创建型模式
java·设计模式
晨米酱19 小时前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机1 天前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机1 天前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——性能模式
python·设计模式·架构
使一颗心免于哀伤1 天前
《设计模式之禅》笔记摘录 - 21.状态模式
笔记·设计模式
数据智能老司机2 天前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
数据智能老司机2 天前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
烛阴2 天前
【TS 设计模式完全指南】懒加载、缓存与权限控制:代理模式在 TypeScript 中的三大妙用
javascript·设计模式·typescript