Java实现单例模式总结

这种

1.单例模式简介

单例模式属于设计模式中的创建型模式。它主要用于一个类只能有一个实例的场景(想想一些只能有一个或者只需要一个的资源的场景),哪怕是多线程在访问这个实例,除此之外,需要提供一个全局访问它的点。

2.单例模式实现的方式

单例模式有很多实现方法,在这里只提供几种常见的,分别是饿汉、懒汉、静态内部类、枚举类

2.1 饿汉

public class HungrySingleton {
    // 饿汉模式,程序启动的时候直接加载 线程安全 线程安全由虚拟机保证
    // 这里使用final关键词是为了防止子类继承破坏单例
    private static final HungrySingleton instance = new HungrySingleton();
    // 构造方法设为私有,防止外部new创建
    private HungrySingleton() {}

    public static HungrySingleton getInstance() {
        return instance;
    }
}

优点:线程安全由虚拟机保证,可靠,外部需要使⽤的时候获取即可。

缺点:

(1)无论程序中是否使用都会在程序启动之初进⾏创建,有可能浪费空间(创建了但不使用)。

(2)这种形式的单例过多可能导致程序启动时间过长。

(3)私有化构造器方法不能防止外部创建会被暴力发射破坏。

2.2 懒汉

顾名思义,只有在真正使用的时候才会加载并创建该单例对象。

对于这种实现方式的单例模式,主要有两种,分别为

public class LazySingleton {
    // 这里使用volatile是为了防止instance = new LazySingleton();发生指令重排
    private static volatile LazySingleton instance;

    private LazySingleton() {};


    public static synchronized LazySingleton LazySingleton() {
        if (null != instance) {
            return instance;
        }
        instance = new LazySingleton();
        return instance;
    }

}

此方法实现主要通过方法锁的形式实现多线程安全,但这种加锁方式过于笨重,多线程在该方法上都是串行化,对于并发量高的常见不建议使用,以下是一种优化后的方案:

public class LazySingleton {
    // 这里使用volatile是为了防止instance = new LazySingleton();发生指令重排
    private static volatile LazySingleton instance;

    public static LazySingleton getInstance() {
        if (null != instance) {
            return instance;
        }

        synchronized (LazySingleton.class) {
            if (null == instance) {
                instance = new LazySingleton();
            }
        }

        return  instance;
    }
}

此方法实现也叫双重校验锁形式的单例,相较于把锁加载方法上,第一重校验单例是否为空就能处理大部分的并发请求,减小了锁的竞争。一定程度上优化了性能。

两个问题:

(1)为什么要双重校验:

有了第一重校验,还要有第二重校验的原因,可以考虑这样一个场景,即两个线程并发访问getInstance方法,且此时还没有创建instance对象,那么两个线程均能通过第一重校验锁,那么到了同步代码块,假设第一个线程先进去创建了单例对象(第二个线程阻塞等待),释放锁,第二个线程进去又一次创建了单例对象(没有第二重校验的话),破坏了单例的特性。

(2)volatile关键词的作用

这里使用volatile关键词的作用主要是为了防止instance = new LazySingleton();语句发生指令重排。这个语句如果发生指令重排,有可能先给instance引用赋值,再调用LazySingleton的构造方法,如果这两个操作之间有别的线程调用getInstance方法,则会返回一个还没有初始化完的LazySingleton对象。

优点:线程安全,懒加载,一定程度上可以节省内存资源。

缺点:加锁的⽅式实现线程安全耗费性能。私有构造器方法防止外部创建会被暴力发射破坏

2.3 枚举

public enum EnumSingleton {
    INSTACE;
}

使用

public class Test {
    public static void main(String[] args) {
        System.out.println(EnumSingleton.INSTACE.toString());
    }
}

优点:线程安全,其线程安全由虚拟机保证,而且可以防止暴力反射破坏单例,总得来说也是一种比较推荐的方式

缺点:饿汉式实现思想。有可能浪费空间,但设计合理可以避免这个问题。

2.4 静态内部类

public class InnerSingleton {

    private InnerSingleton() {}

    private static class InnerClass {
        private static InnerSingleton instance = new InnerSingleton();
    }

    public static InnerSingleton getInstance() {
        return InnerClass.instance;
    }
}

优点:不用加锁实现两线程安全,其线程安全由虚拟机保证,且也实现了懒加载的思想,用的时候再创建,这是一种比较推荐的单例模式实现方式。

缺点:私有化构造器方法不能防止外部创建会被暴力发射破坏。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java单例模式包括饿汉式和懒汉式两种实现方式。饿汉式是在类加载阶段就创建实例并持有,而懒汉式则是在需要时才创建实例。 饿汉模式是指在类加载阶段就创建出实例的,因此它的实例化过程相对于普通情况要早很多。这也是为什么叫“饿汉”的原因,就像一个饥饿的人对食物没有抵抗力,一下子就开始吃了一样。 懒汉模式是指在需要时才创建实例。这种方式的优点是节省了资源,只有在需要时才会进行实例化。但是它的缺点是在多线程环境下可能会导致多个线程同时创建实例的问题,需要进行额外的线程安全措施来解决这个问题。 总结来说,饿汉式适合在应用启动时就需要创建实例的情况,因为它的实例化过程早于普通情况。而懒汉式适合在需要时才创建实例的情况,可以节省资源。 需要注意的是,单例模式的使用要根据具体的适应场景来决定,不同的情况下选择不同的实现方式。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Java设计模式之单例模式——饿汉式、懒汉式(初了解)](https://blog.csdn.net/m0_68062837/article/details/127307310)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Java多线程案例之单例模式(饿汉,懒汉)](https://blog.csdn.net/qq_63218110/article/details/128738155)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值