单例模式

核心作用

:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点

常见场景

标题Windows的任务管理器
Windows的回收站
项目中,读取配置文件的类,一般也只有一个对象,没有必要每次都去new新对象读取
网站的计时器也会采用单例,保证同步
数据库连接池的设计一般也是单例模式
在Servlet编程中,每个Servlet也是单例
在Spring中,每个Bean默认就是单例

优点

由于单例模式只生成一个实例,减少了系统性能的开销
单例模式可以在系统设置全局的访问点,优化共享资源访问

常见五种单例模式实现方法

饿汉式(线程安全,调用效率高,不能延时加载)
懒汉式(线程安全,调用效率不高,可以延时加载)
DCL懒汉式(由于JVM底层内部模型的原因,偶尔会出现问题,不推荐使用)
饿汉式改进:静态内部类式(线程安全,调用效率高,可以延时加载)
枚举单例:(线程安全,调用效率高,不能延时加载)

1.饿汉式(线程安全,调用效率高,不能延时加载)

public class Danli {
    //私有化构造器
    private Danli() {}
    
    //类初始化的时候就立即生成一个单例
    private static Danli instance = new Danli();
    
    //获取单例的方法,没有synchronized,效率高!
    public static Danli getInstance(){
        return instance;
    }
}

2.懒汉式(线程安全,调用效率不高,可以延时加载)

public class Danli2 {
    //私有化构造器
    private Danli2() {}

    //类初始化的时候,不立即加载该对象
    private static Danli2 instance;
    
    //获取单例的方法,有synchronized,效率不高!
    public static synchronized Danli2 getInstance(){
        if(instance==null)
            instance = new Danli2();
        return instance;
    }
}

3.DCL懒汉式(由于JVM底层内部模型的原因,偶尔会出现问题,不推荐使用)

public class Danli3 {
    //私有化构造器
    private Danli3() {}

    //类初始化的时候,不立即加载该对象,volatile保证创建过程的原子性
    private volatile static Danli3 instance;
    
    //获取单例的方法,有synchronized,效率不高!
    public static synchronized Danli3 getInstance(){
        if(instance==null){
            synchronized (Danli3.class){
                if(instance==null)
                    instance = new Danli3();
            }
        }
        return instance;
    }
}

4.饿汉式改进:静态内部类式(线程安全,调用效率高,可以延时加载)

package com.hzj.pojo;
//饿汉式(线程安全,调用效率高,不能延时加载)
public class Danli3 {
    //私有化构造器
    private Danli3() {}

    //静态内部类,final保证instance只有一个
    private static class InnerClass{
        private static final Danli3 instance = new Danli3();
    }


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



注:但仍然可以通过反射的方式来破坏单例

5.枚举单例:(线程安全,调用效率高,不能延时加载)

class Test{
    public static void main(String[] args) throws Exception {
        Danli3 instance = Danli3.getInstance();
        Constructor<Danli3> declaredConstructor = Danli3.class.getDeclaredConstructor(null);
        //将权限破坏
        declaredConstructor.setAccessible(true);
        Danli3 instance2 = declaredConstructor.newInstance();
        System.out.println(instance==instance2);//false,说明instance2是新的对象,单例模式被破坏
    }
}
public enum Danli {
    INSTANCE;
    public Danli getInstance(){
        return INSTANCE;
    }
}

Constructor.class newInstance方法源码天然屏蔽了Enum对象

public T newInstance(Object... initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        if (!this.override) {
            Class<?> caller = Reflection.getCallerClass();
            this.checkAccess(caller, this.clazz, this.clazz, this.modifiers);
        }

        if ((this.clazz.getModifiers() & 16384) != 0) {
        //反射源码中,不能new一个枚举对象
            throw new IllegalArgumentException("Cannot reflectively create enum objects");
        } else {
            ConstructorAccessor ca = this.constructorAccessor;
            if (ca == null) {
                ca = this.acquireConstructorAccessor();
            }

            T inst = ca.newInstance(initargs);
            return inst;
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值