八种单例模式详解

亲爱的朋友们,大家好!

今天是 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.总结

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

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

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

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

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

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

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

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

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

相关推荐
code bean2 天前
【wpf】WPF开发避坑指南:单例模式中依赖注入导致XAML设计器崩溃的解决方案
单例模式·wpf
是三好3 天前
单例模式(Singleton Pattern)
java·开发语言·算法·单例模式
青春易逝丶3 天前
单例模式
单例模式
YA3334 天前
java设计模式一、单例模式
java·单例模式·设计模式
枫景Maple4 天前
Unity中多线程与高并发下的单例模式
unity·单例模式·游戏引擎
iiiiaaiashah4 天前
单例模式的mock类注入单元测试与友元类解决方案
java·开发语言·单例模式
jingfeng5148 天前
线程池及线程池单例模式
linux·开发语言·单例模式
Brookty8 天前
深入解析Java并发编程与单例模式
java·开发语言·学习·单例模式·java-ee
Meteors.9 天前
23种设计模式——单例模式(Singleton)详解
单例模式·设计模式
东北南西14 天前
设计模式-单例模式
前端·javascript·单例模式·设计模式