单例模式Demo

本文详细介绍了Java中的单例模式,包括懒汉式和饿汉式的实现,以及它们在多线程环境下的问题和解决方案。通过示例代码展示了不同单例模式的优缺点,如懒汉式的延迟加载和饿汉式的类加载时初始化。讨论了双重检查锁定、静态内部类和枚举等优化策略,确保线程安全并提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

**单例模式 顾名思义就是在程序中只有一个实例对象
单例模式具体大致分为两种类型:
1.懒汉式

  • 懒汉式顾名思义就是能有多懒他就多懒,能不’动’他就不动

  • 懒汉式只有在需要他的时候他才会去加载,完成实例化

2.饿汉式

  • 饿汉式顾明思义就是不管三七二十一就是要’吃’,不管是否需要,先’吃’了再说

  • 饿汉式在程序类加载的时候完成实例化

以下是各实例的Demo
1.饿汉式

/**
 * 饿汉式(最常见)
 *  类加载到内存后,就实例化一个单例,JVM保证线程的安全
 *  1.将对象声明
 *  2.对象的构造方法设为私有属性,用户在使用的时候无法去声明创建对象
 *  3.写一个getInstance方法,去返回类中声明的唯一对象
 *  缺点:类加载的时候完成实例化
 */
public class Singleton {

    private static final Singleton singleton=new Singleton();

    private Singleton(){};

    public static Singleton getInstance(){
        return singleton;

    }

    public static void main(String[] args) {
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance.hashCode());
        System.out.println(instance2.hashCode());
    }
    //两者输出的hash值一致

2.懒汉式

/**
 * 懒汉式
 *  1.声明实例,但是不初始化
 *  2.在构造方法私有化
 *  3.在调取getInstance进行对象返回的时候,判断对象是否为null,是否初始化完成
 *      3.1 初始化完成,既不为null,那就返回对象,否则进行对象的初始化
 *  缺点:  在多线程的访问中是有问题的 ---不安全
 */
public class Singleton01 {

    private static  Singleton01 singleton=null;

    private Singleton01(){};

    public static Singleton01 getInstance(){
        if(singleton==null){
            try {
                Thread.sleep(1);
            } catch (Exception e) {
                e.printStackTrace();
            }
            singleton=new Singleton01();
        }
        return singleton;

    }

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

3.懒汉式(改进上个版本多线程下出现的问题)
在方法上加锁 加锁的同时,会影响程序的效率

/**
 * 懒汉式
 *  1.声明实例,但是不初始化
 *  2.在构造方法私有化
 *  3.在调取getInstance进行对象返回的时候,判断对象是否为null,是否初始化完成
 *      3.1 初始化完成,既不为null,那就返回对象,否则进行对象的初始化
 *  缺点:  在多线程的访问中是有问题的 ---不安全
 *
 *  修改 01: 在方法上加锁   加锁的同时,会影响程序的效率
 */
public class Singleton02 {

    private static Singleton02 singleton=null;

    private Singleton02(){};

    public static synchronized Singleton02 getInstance(){
        if(singleton==null){
            try {
                Thread.sleep(1);
            } catch (Exception e) {
                e.printStackTrace();
            }
            singleton=new Singleton02();
        }
        return singleton;

    }

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

4.懒汉式(上个版本在方法上加锁,导致程序的运行效率大大降低)
改进: 在方法内部加锁

/**
 * 懒汉式  (较为完美)
 *  1.声明实例,但是不初始化
 *  2.在构造方法私有化
 *  3.在调取getInstance进行对象返回的时候,判断对象是否为null,是否初始化完成
 *      3.1 初始化完成,既不为null,那就返回对象,否则进行对象的初始化
 *  缺点:  在多线程的访问中是有问题的 ---不安全
 *
 *  修改 01: 在方法内部加锁   加锁的同时,会影响程序的效率
 *      需要进行两次判空,一次判断在多线程的时候,容易造成多次声明对象
 */
public class Singleton03 {

    private static Singleton03 singleton=null;

    private Singleton03(){};

    public static  Singleton03 getInstance(){
        if(singleton==null){
            synchronized (Singleton03.class) {
                if(singleton==null) {
                    try {
                        Thread.sleep(1);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    singleton = new Singleton03();
                }
            }
        }
        return singleton;

    }

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

在方法内部加锁比在方法上加锁,效率影响小

5.懒汉式(懒汉式目前完美的方法)

/**
 * 懒汉式(完美)
 * 1.声明一个静态内部类的对象声明
 *  JVM保证线程安全
 */
public class Singleton04 {



    private Singleton04(){};

    private static class  MySingleton04{
        private static final Singleton04 singleton=new Singleton04();
    }

    public static Singleton04 getInstance(){

        return MySingleton04.singleton;

    }

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

6.使用枚举类完成懒汉式

/**
 * 懒汉式(完美)
 *  优点:使用JDK1.5提供的枚举来实现单例设计模式,不仅能避免多线程同步问题,
 *  而且还能防止反序列化创建新的对象,这种方式是Effective java中提倡的方式
 *
 */
public enum  Singleton05 {

    INSTANCE;

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

以上便是对单例模式较为详细的Demo,目前还是对枚举类的这种方法有点懵,如果有大佬看到,还请指点一二!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值