八种单例模式详解

亲爱的朋友们,大家好!

今天是 CSDN博客之星 投票的开始日!非常感谢你们在过去的时间里给予我无私的支持和鼓励,这一路走来,正是因为有你们的帮助,我才能不断进步,走得更远。

目前,投票已正式开启(2月14日到2月20日,一共七天,每天都可以投 ),如果你们愿意支持我,可以通过以下链接给67号进行投票:

点击这里投票

我非常珍惜你们的每一份支持,这对我意义重大,也将是我不断前进的动力!如果你们能为我投上宝贵的一票,我会更加努力,继续为大家带来更多有价值的技术分享。另外,这是我半年时间自研的 Java 框架 Sunrays-Framework

Sunrays-Framework官方文档

如果有兴趣,欢迎随时取用!

再次感谢大家的支持与鼓励,期待我们一起成长!


文章目录

1.单例模式饿汉式(静态变量)

java 复制代码
package com.sunxiansheng.design_pattern.singleton;

/**
 * Description: 单例模式饿汉式(静态变量)
 *
 * @Author sun
 * @Create 2025/1/17 15:12
 * @Version 1.0
 */
public class TypeA {

    public static void main(String[] args) {
        Singleton singletonA = Singleton.getInstance();
        Singleton singletonB = Singleton.getInstance();
        System.out.println(singletonA == singletonB);
    }
}

class Singleton {

    /**
     * 构造器私有化
     */
    private Singleton() {
    }

    /**
     * 静态变量
     */
    private static final Singleton INSTANCE = new Singleton();

    /**
     * 暴露单例对象
     *
     * @return
     */
    public static Singleton getInstance() {
        return INSTANCE;
    }
}

2.单例模式饿汉式(静态代码块)

java 复制代码
package com.sunxiansheng.design_pattern.singleton.TypeB;

/**
 * Description: 单例模式饿汉式(静态代码块)
 *
 * @Author sun
 * @Create 2025/1/17 15:15
 * @Version 1.0
 */
public class TypeB {

    public static void main(String[] args) {
        Singleton singletonA = Singleton.getInstance();
        Singleton singletonB = Singleton.getInstance();
        System.out.println(singletonB == singletonB);
    }
}

class Singleton {

    /**
     * 构造器私有化
     */
    private Singleton() {
    }

    /**
     * 静态单例对象声明
     */
    private static Singleton INSTANCE;

    /**
     * 静态代码块初始化单例对象
     */
    static {
        INSTANCE = new Singleton();
    }

    /**
     * 向外暴露单例对象
     *
     * @return
     */
    public static Singleton getInstance() {
        return INSTANCE;
    }
}

3.单例模式懒汉式(线程不安全)

java 复制代码
package com.sunxiansheng.design_pattern.singleton.TypeC;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

/**
 * Description: 单例模式懒汉式(线程不安全)
 *
 * @Author sun
 * @Create 2025/1/17 15:22
 * @Version 1.0
 */
public class TypeC {
}

class Singleton {

    /**
     * 构造器私有化
     */
    private Singleton() {
    }

    /**
     * 静态变量
     */
    private static Singleton INSTANCE;

    /**
     * 对外暴露单例对象
     *
     * @return
     */
    public static Singleton getInstance() {
        // 只有当静态变量为空的时候才赋值
        if (INSTANCE == null) {
            INSTANCE = new Singleton();
        }
        return INSTANCE;
    }
}

4.单例模式懒汉式(同步方法)

java 复制代码
package com.sunxiansheng.design_pattern.singleton.TypeD;

/**
 * Description: 单例模式懒汉式(同步方法)
 *
 * @Author sun
 * @Create 2025/1/17 15:36
 * @Version 1.0
 */
public class TypeD {
}

class Singleton {

    /**
     * 构造器私有化
     */
    private Singleton() {
    }

    /**
     * 静态属性
     */
    private static Singleton INSTANCE;

    /**
     * 同步方法,保证线程安全
     *
     * @return
     */
    public synchronized static Singleton getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new Singleton();
        }
        return INSTANCE;
    }
}

5.单例模式饿汉式(同步代码块,线程不安全)

java 复制代码
package com.sunxiansheng.design_pattern.singleton.TypeE;

/**
 * Description: 单例模式饿汉式(同步代码块,线程不安全)
 *
 * @Author sun
 * @Create 2025/1/22 15:15
 * @Version 1.0
 */
public class TypeE {


}

class Singleton {

    /**
     * 构造器私有化
     */
    private Singleton() {
    }

    /**
     * 静态变量
     */
    private static Singleton singleton;

    /**
     * 向外暴露单例对象
     *
     * @return
     */
    public static Singleton getInstance() {
        if (singleton == null) {
            // 使用一个同步代码块来解决
            synchronized (Singleton.class) {
                singleton = new Singleton();
            }
        }
        return singleton;
    }
}

6.单例模式懒汉式(双检锁)

java 复制代码
package com.sunxiansheng.design_pattern.singleton.TypeF;

/**
 * Description: 单例模式懒汉式(双检锁)
 *
 * @Author sun
 * @Create 2025/1/22 15:25
 * @Version 1.0
 */
public class TypeF {
}

class Singleton {

    /**
     * 构造器私有化
     */
    private Singleton() {
    }

    /**
     * 静态变量,volatile保证可见性
     */
    private static volatile Singleton instance;

    /**
     * 向外暴露单例对象
     *
     * @return
     */
    public static Singleton getInstance() {
        // 1.判空
        if (instance == null) {
            // 2.加锁
            synchronized (Singleton.class) {
                // 3.再判空
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

7.单例模式懒汉式(静态内部类)

java 复制代码
package com.sunxiansheng.design_pattern.singleton.TypeG;

/**
 * Description: 单例模式懒汉式(静态内部类)
 *
 * @Author sun
 * @Create 2025/1/22 15:35
 * @Version 1.0
 */
public class TypeG {
}

class Singleton {

    /**
     * 构造器私有化
     */
    private Singleton() {
    }

    /**
     * 静态内部类,里面有一个静态常量
     */
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    /**
     * 暴露方法,加载静态内部类,并获取对象
     *
     * @return
     */
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

8.单例模式饿汉式(枚举实现)

java 复制代码
package com.sunxiansheng.design_pattern.singleton.TypeH;

/**
 * Description: 单例模式饿汉式(枚举实现)
 *
 * @Author sun
 * @Create 2025/1/22 15:42
 * @Version 1.0
 */
public class TypeH {
}

enum Singleton {

    /**
     * 天生的单例对象
     */
    SINGLETON(1, "sun")
    ;

    private int age;

    private String name;

    /**
     * 构造器默认是私有化的
     *
     * @param age
     * @param name
     */
    Singleton(int age, String name) {
        this.age = age;
        this.name = name;
    }
}

9.总结

单例模式共有八种,其中包含几种典型错误!

第一种是通过静态变量来实现,也就是利用了类只加载一次的特性去完成的。

第二种是通过静态代码块来实现对静态变量的赋值,本质跟第一种没有区别。

第三种是想要实现一个懒汉式,就直接判断变量不为空的时候再赋值,但是会有线程安全问题。

第四种是为了保证线程安全,就采用了同步方法,这样虽然可以解决问题,但是锁的粒度太大。

第五种是为了降低锁的粒度,想要使用同步代码块加在创建实例的部分,但是是没用的,因为可以有多个线程同时判断变量为空,从而进来创建对象,这样做只能保证按照顺序的创建对象,并不能保证不会多次创建对象。

第六种就是既可以降低锁的粒度又可以保证线程安全的双检锁,采用判空,加锁,再判空的方式来完成单例对象的创建。

第七种是静态内部类的方式,就是编写一个静态内部类,持有着静态常量,类加载并不会加载静态内部类,所以外部类在需要的时候去拿这个单例对象即可。

第八种是枚举实现,枚举可以说是最佳的单例实现方式,只要只创建一个枚举对象,那么就是单例的了。

相关推荐
yuanpan1 天前
23种设计模式之《单例模式(Singleton)》在c#中的应用及理解
单例模式·设计模式·c#
小突突突1 天前
总结单例模式的写法(在线程安全的情况下)
java·开发语言·后端·单例模式·java-ee
老朋友此林1 天前
详解单例模式、模板方法及项目和源码应用
java·开发语言·单例模式
one客1 天前
设计模式 - 单例模式
c++·单例模式·设计模式
It_BeeCoder2 天前
Java:单例模式(Singleton Pattern)及实现方式
java·单例模式·程序员
卷福同学3 天前
设计模式2:单例模式
java·单例模式·设计模式
道友老李3 天前
【设计模式精讲】创建型模式之单例模式(饿汉式、懒汉式、双重校验、静态内部类、枚举)
单例模式·设计模式
小刘|3 天前
Java 多线程编程与单例模式
java·开发语言·单例模式
bing_1586 天前
Java 单例模式 (Singleton)
java·开发语言·单例模式