单例模式a

为什么需要单例模式?

保证类的实例在全局只有一个,避免无效对象创建和销毁时的资源消耗。

在Java中一切都是对象,实例方法的调用需要通过对象,为了调用类中的方法而创建对象,方法调用完成之后对象也需要被GC回收,资源消耗较大。

单例模式有多种实现方式

饿汉式

程序启动即创建单例对象,系统运行中减少对象的创建时间,程序启动较慢,运行过程中响应较快,如果程序整个生命周期中没有用到该单例对象会造成资源的浪费(创建对象和销毁对象)。

java 复制代码
public class Singleton1 {

    private Singleton1(){}

    // 饿汉式,程序启动时创建对象,启动耗时,如果对象在整个声明周期内没有使用那么对象创建及销毁浪费时间
    private static Singleton1 instance = new Singleton1();

    public static Singleton1 getInstance() {
        return instance;
    }
}
懒汉式

程序启动时不创建对象,在运行的过程中第一次使用时才创建对象,程序启动较快。

同步方法

所有的并发操作都会进行阻塞,效率较低

java 复制代码
public class Singleton2 {
    private Singleton2(){}
    private static Singleton2 instance = null;
    public static synchronized Singleton2 getInstance(){
        if (instance == null) {
            instance = new Singleton2();
        }
        return instance;
    }
}
DCL

将同步方法修改为同步代码块,为了保证性能和功能需要使用双重锁判断(Double Check Lock)

需要将单例引用使用 volatile 修饰

java 复制代码
public class Singleton3 {
    private Singleton3(){}
    // DCL 方式需要使用volatile进行修饰
    private volatile static Singleton3 instance = null;
    public static Singleton3 getInstance(){
        // DCL(Double Check Lock) 双重锁检查,保证单例的正确和性能
        if (instance == null) { // 保证性能,只有第一次并发的线程才会进入代码块内部
            synchronized (Singleton3.class){
                if (instance == null) { // 保证正确,第一次并发进来的线程也会进行判断
                    instance = new Singleton3();
                }
            }
        }
        return instance;
    }
}
静态内部类

静态内部类在单例类中声明一个持有单例对象的内部类,在获取单例对象时从静态内部类中获取持有的单例对象,方法需要使用 final 修饰。

java 复制代码
public class Singleton4 implements Serializable {
    private Singleton4(){}
    private static Singleton4 instance = null;
    private static class SingletonHolder{
        private static Singleton4 instance = new Singleton4();
    }

    public static final Singleton4 getInstance() {
        return SingletonHolder.instance;
    }

}

以上四种方式都是

1:将单例类的构造函数私有化,

2:在类内部创建对象,

3:通过方法暴漏给用户

如果对单例对象进行序列化和反序列化也将得到不同的对象,这个问题可以在单例类内部添加 readResolve方法 解决。

枚举

"单元素枚举类已成为Singleton的最佳方法。"-----《effective java》

java 复制代码
public enum Singleton5 {
    INSTANCE;
    int value;
    private Singleton5(){
        System.out.println("Singleton5 is created ! ");
    }
    public int getValue(){
        return value;
    }
    public void setValue(int value){
        this.value = value;
    }

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