单例模式

定义

一个类有且仅有一个实例,并且自行实例化向整个系统提供。(创建型模式)设计模式中比较简单的几种之一,单例模式就是让一个类在系统运行过程中只会产生唯一的一个实例,单例模式主要:

  1. 单例类只能有一个实例。
  2. 单例类必须自己创建自己的唯一实例。
  3. 单例类必须给所有其他对象提供这一实例。

使用场景

  • 需要频繁实例化然后销毁的对象。
  • 创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
  • 有状态的工具类对象。
  • 频繁访问数据库或文件的对象。

1、懒汉式典型实现

复制代码
public class SingletonLazy {
    private static SingletonLazy singletonLazy;
    private SingletonLazy (){}
    public static SingletonLazy getInstance(){
        if( singletonLazy == null){
            singletonLazy = new SingletonLazy();
        }
        return singletonLazy;
    }
}

懒汉式的模式就是在需要进行实例化的时候在进行实例化,这种方式在多线程的时候是有问题的,会有线程安全问题。

2、懒汉式线程安全形式

复制代码
public class SingletonLazeSafe {
    private static SingletonLazeSafe singletonLazeSafe;
    private SingletonLazeSafe(){}
    public static synchronized SingletonLazeSafe getInstance(){
        if(singletonLazeSafe == null){
            singletonLazeSafe = new SingletonLazeSafe();
        }
        return singletonLazeSafe;
    }
}

懒汉式的线程安全模式在进入获取实例方法时候就会加synchronize,可以保证线程安全获取唯一的实例,但是如果该方法调用过多会有性能方面的影响。

3、饿汉式

复制代码
public class SingletonHungary {
    private static SingletonHungary singletonHungary = new SingletonHungary();
    private SingletonHungary(){}
    public static SingletonHungary getInstance(){
        return singletonHungary;
    }
}

饿汉式会在类装载时候就进行实例的初始化,虽然没有了synchronize的效率影响,但是在类加载的时候就进行了初始化一方面浪费了内存,也没有实现lazy loading加载的效果。

4、双重校验锁

复制代码
public class DoubleCheckedLocking {
    private static DoubleCheckedLocking doubleCheckedLocking;
    private DoubleCheckedLocking(){}
    public DoubleCheckedLocking getInstance(){
        if(doubleCheckedLocking == null){
            synchronized (DoubleCheckedLocking.class){
                if(doubleCheckedLocking == null){
                    doubleCheckedLocking = new DoubleCheckedLocking();
                }
            }
        }
        return doubleCheckedLocking;
    }
}

这种方式采用了双锁机制,一方面保证了多线程的安全,另一方面还提高了效率。

5、静态内部类

复制代码
public class SingletonStaticClass {
    //静态内部类
    private static class SingletonHodler{
        private static final SingletonStaticClass INSTANCE = new SingletonStaticClass();
    }
    private SingletonStaticClass(){}
    public static final SingletonStaticClass getInstance(){
        return SingletonHodler.INSTANCE;
    }
}

这种方式利用了 classloder 机制来保证初始化 instance 时只有一个线程,但是这个是类装载的时候不一定会进行初始化,只有在调用 getInstance 方法时候才会显示的装载SingletonHodler,然后实例化instance。

6、枚举

复制代码
public enum EnumSingleton {
    INSTANCE;
}

枚举的方式最简单,又是线程安全的(默认枚举实例的创建是线程安全的)

相关推荐
重生之我是Java开发战士6 天前
【Java SE】多线程(三):单例模式,阻塞队列,线程池与定时器
java·javascript·单例模式
许彰午7 天前
34_Java设计模式之单例模式
java·单例模式·设计模式
罗超驿9 天前
10.Java单例模式全解析:饿汉式与懒汉式实现及线程安全深度剖析
安全·单例模式·javaee
布朗克1689 天前
33 设计模式精讲
java·单例模式·设计模式
雨浓YN9 天前
基于设计模式的Winform软件框架-01Xml\Log\Ini日志(单例模式+生产者消费者模式)
单例模式·设计模式
仙俊红10 天前
Java 单例模式:类里面为什么可以有自己类型的字段?
java·开发语言·单例模式
swordbob10 天前
prototype 注入到 singleton 里,prototype是否还是线程安全的
安全·spring·单例模式·原型模式
谁似人间西林客12 天前
工业大数据实战:看中国智造如何用数据驱动效率革命
大数据·单例模式
张小姐的猫12 天前
【Linux】多线程 —— 线程池 | 单例模式 | 常见锁
linux·运维·服务器·c++·单例模式·设计模式·策略模式
Java面试题总结13 天前
双重检验锁的单例模式在高并发下的可见性问题
单例模式