设计模式~单列模式-01

简介: 单列模式1、饿汉式2、懒汉式(lazy loading)3、双重检测4、静态内部类

单列模式

1、饿汉式

2、懒汉式(lazy loading)

3、双重检测

4、静态内部类(完美)

5、枚举单列(最完美)


       单例模式就是为了确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。单例模式控制控制对象不要反复创建,提高我们工作的效率。减少资源的占用。

       【解释:我有 6 个漂亮的老婆,她们的老公都是我,我就是我们家里的老公 Sigleton,她们只要说道「老公」,都是指的同一个人,那就是我 。】

(1)单例模式下类的组成部分:

       1.私有的构造方法。

       2.私有的当前类对象作为静态属性。

       3.公有的向外界提供当前类对象的静态方法。

主要的两种实现方式:

       饿汉式:线程安全,调用效率高,不能延时加载。

       懒汉式:线程安全,调用效率不高,可以延时加载。

其他方式:

       双重检测锁式:极端情况下偶尔会出现问题,不建议使用。

       静态内部类式:线程安全,调用效率高,可以延时加载。

       枚举式:线程安全,调用效率高,不能延时加载。

2懒汉式饿汉式的区别

       “懒汉式”是在你真正用到的时候才去建这个单例对象“饿汉式”是在不管用不用得上,一开始就建立这个单例对象

       从实现方式来讲他们最大的区别就是懒汉式是延时加载,他是在需要的时候才创建对象,而饿汉式在虚拟机启动的时候就会创建,饿汉式无需关注多线程问题,写法简单明了,能用则用。但是它是加载类时创建实例。

       饿汉式是线程安全的,在类创建的同时就已经创建好一个静态的对象供系统使用,以后不在改变。懒汉式如果在创建实例对象时不加上synchronized则会导致对对象的访问不是线程安全的。

       只是一个语法的标识,就好比文档中的句号和逗号差不多,代表当前是一个完整的语句,和下一个语法分开,如果仅仅只有一句,加不加无所谓,但是多个语句时,要区分,否则编译器不知道你的语法。

1、饿汉式

       类加载到内存后,就实例化一个单例,JVM保证线程安全。

       简单实用,推荐使用!

       唯一缺点:不管用到与否,类装载时就完成实例化。

public class Singleton01 {
    //持有私有静态实例,防止被引用
private static final Singleton01 INSTANCE = new Singleton01();
//    private static final Singleton01 INSTANCE;
//    static {
//        INSTANCE = new Singleton01();
//    }
//私有构造方法,防止被实例化
//只有本类能调用,只能Singleton01 Singleton = Singleton01.getInstance();调用
private Singleton01() {};//分号:增加语法的可读性
/*只是一个语法的标识,就好比文档中的句号和逗号差不多,代表当前是一个完整的语句,和下一个语法分开,如果仅仅只有一句,加不加无所谓,但是多个语句时,要区分,否则编译器不知道你的语法。*/
//懒汉式,静态工程方法,创建实例
    public static Singleton01 getInstance() {
        return INSTANCE;
}
//可有可无
    public void m() {
        System.out.println("m");
    }
    public static void main(String[] args) {
        Singleton01 m1 = Singleton01.getInstance();
        Singleton01 m2 = Singleton01.getInstance();
        System.out.println(m1 == m2);
    }
}

2、懒汉式lazy loading

       虽然达到了按需初始化的目的,但却带来线程不安全的问题。

       可以通过synchronized解决,但也带来效率下降。延迟加载,也叫作懒加载,等到真正用的时候才加载。

public class Singleton02 {
//持有私有静态实例,防止被引用
    private static Singleton04 INSTANCE;
    //私有构造方法,防止被实例化
    private Singleton02() {
    }
    //懒汉式,静态工程方法,创建实例
    //加锁(synchronized)效率下降
    public static /*synchronized*/ Singleton02 getInstance() {
        if (INSTANCE == null) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //妄图通过减小同步代码块的方式提高效率,然后不可行
//            synchronized (Singleton02.class) {
//                try {
//                    Thread.sleep(1);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
            INSTANCE = new Singleton02();
        }
        return INSTANCE;
    }
    public void m() {
        System.out.println("m");
    }
    public static void main(String[] args) {
        for(int i=0; i<100; i++) {
            new Thread(()->{
                System.out.println(Singleton02.getInstance().hashCode());
            }).start();
        }
    }
}

3、双重检测

       保证线程安全;以前认为是最完美的方式。

public class Singleton03 {
    //volatile:不写,会出现。volatile 防止指令重排和可见性
    private static volatile Singleton03 INSTANCE; //JIT
    private Singleton03() {
    }
public static Singleton03 getInstance() {
//判断对象是否已经实例化,只有非实例化的情况下才能进入if块进行加锁。
        if (INSTANCE == null) {
            //双重检查:保证线程安全;以前认为是最完美的方式
            synchronized (Singleton03.class) {
//避免 SingletonTon== null时,第一个线程实例化后,进入阻塞状态的线程被唤醒后仍会进行实例化。
                if(INSTANCE == null) {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    INSTANCE = new Singleton03();
                }
            }
        }
        return INSTANCE;
    }
    public void m() {
        System.out.println("m");
    }
    public static void main(String[] args) {
        for(int i=0; i<100; i++) {
            new Thread(()->{
                System.out.println(Singleton03.getInstance().hashCode());
            }).start();
        }
    }
}

4、静态内部类(完美)

       静态内部类方式,完美。JVM保证单例线程安全,加载外部类时不会加载内部类,这样可以实现懒加载。

public class Singleton04 {//JVM只加载一次
//私有构造方法
    private Singleton04() {
    }
    //静态内部类,初始化04
private static class Singleton07Holder {
//组合外部类对象作为属性
        private final static Singleton04 INSTANCE = new Singleton04();//出现延迟加载
    }
    public static Singleton04 getInstance() {
        return Singleton04Holder.INSTANCE;
    }
    public void m() {
        System.out.println("m");
    }
    public static void main(String[] args) {
        for(int i=0; i<100; i++) {
            new Thread(()->{
                System.out.println(Singleton04.getInstance().hashCode());
            }).start();
        }
    }
}

5、枚举单列最完美

       不仅可以解决线程同步,还可以防止反序列化。由JVM从根本上提供保障!避免通过反射和反序列化的漏洞!

public enum Singletontonton05 {
    INSTANCE;
    public void m() {}
    public static void main(String[] args) {
        for(int i=0; i<100; i++) {
            new Thread(()->{
                System.out.println(Singletonton05.INSTANCE.hashCode());
            }).start();
        }
    }
}


目录
相关文章
|
8月前
|
设计模式 算法 Java
C++设计模式
C++设计模式
51 0
|
3月前
|
设计模式 安全 Java
24种设计模式详解(下)
24种设计模式详解(下)
42 0
|
8月前
|
设计模式 缓存 算法
设计模式
设计模式
51 0
|
8月前
|
设计模式 数据中心
常用设计模式这样学
常用设计模式这样学
|
8月前
|
设计模式 自动驾驶 NoSQL
设计模式总结(一)
设计模式总结(一)
|
设计模式 安全 Java
设计模式之单列模式
设计模式之单列模式
72 0
|
设计模式
23种设计模式
23种设计模式主要分为三大类:创建型模式、结构型模式和行为型模式。
82 0
|
设计模式 算法 程序员
2023-6-9-一天一种设计模式
2023-6-9-一天一种设计模式
85 0
|
设计模式
设计模式总结
设计模式总结
84 0
|
设计模式 消息中间件 Java
一起来学设计模式之认识设计模式
前言 目前正在出一个设计模式专题系列教程, 篇幅会较多, 喜欢的话,给个关注❤️ ~ 本节给大家讲一下设计模式基本概念,它的基本原则以及有哪些设计模式~ 本专题的所有案例代码主要以Java语言为主, 好了, 废话不多说直接开整吧~ 设计模式初识 设计模式是一种经过验证的、被广泛应用的解决特定问题的软件设计方案,它提供了一种在软件设计中反复使用的解决方案。设计模式通常描述了一个问题的情境、解决方案和解决方案的优点和缺点。设计模式不是一种具体的编程语言特性或库,而是一种通用的设计思想和方法。