• 设计模式之单例模式


    单例模式的几种实现

    所谓单例,就是整个程序有且仅有一个实例。该类负责创建自己的对象,同时确保只有一个对象被创建。在Java,一般常用在工具类的实现。

    特点

    • 类构造器私有
    • 持有自己类型的属性
    • 对外提供获取实例的静态方法

    实现方式:

    饿汉模式

    线程安全,比较常用,但是会浪费空间,因为一开始就初始化

    public class Singleton{
        private Singleton(){}
        
        private final static Singleton instance = new Singleton();
        
        public static Singleton getInstance(){
            return instance;
        }
    }
    

    懒汉模式

    线程不安全,延迟初始化,容易被反射攻击

    public class Singleton{
        private Singleton(){}
        
        private static Singleton instance = null;
        
        public static Singleton getInstance(){
            if (instance == null) {
                instance = new LazyMan();
            }
            return instance;
        }
    }
    

    懒汉模式:双重校验锁

    public class Singleton{
        private Singleton(){}
        
        // 双重锁必须加 volatile
        private volatile static Singleton instance = null;
        
        public static Singleton getInstance(){
            if (instance == null) {
                synchronized (Singleton.class){
                    if(instance == null){
                        instance = new Singleton();	// 不是原子操作
                      	/**
                      	 * 1. 分配内存
                      	 * 2. 执行构造
                      	 * 3. 对象指向内存
                      	 * 可能发生重排
                      	 */
                    }
                }
            }
            return instance;
        }
    }
    

    双重检查模式,进行了两次的判断,第一次是为了避免不要的实例,第二次是为了进行同步,避免多线程问题。由于singleton=new Singleton()对象的创建在JVM中可能会进行重排序,在多线程访问下存在风险,使用volatile修饰signleton实例变量有效,解决该问题。

    懒汉模式:静态内部类

    public class Singleton{
        private Singleton(){}
        
        private static class Inner{
            private static final Singleton instance = new Singleton();
        }
        
        public static Singleton getInstance(){
            return Inner.instance
        }
    }
    

    第一次调用getInstance方法时,虚拟机才加载 Inner 并初始化instance。


    通过反射破坏:

    Singleton instance  = Singleton.getInstance();
    
    Constructor<Singleton> declaredConstructor = Singleton.class.getDeclaredConstructor();
    declaredConstructor.setAccessible(true);
    Singleton instance2 = declaredConstructor.newInstance();
    
    System.out.println(instance == instance2); //false
    

    懒汉模式:枚举

    枚举本身是一个类

    // 枚举方式 极为推荐的方式
    enum Singleton {
        INSTANCE; //定义一个枚举的元素,就代表一个实例
        //一个enum的构造方法限制是private的
    
        public static Singleton getInstance() {
            return INSTANCE;
        }
    }
    

    使用:

    Singleton instance = Singleton.INSTANCE;
    Singleton instance = Singleton.getInstance();
    
  • 相关阅读:
    [视频]K8飞刀--WinRAR远程代码执行漏洞利用视频
    [视频]K8飞刀 SQL注入点脱库演示教程
    [视频]K8飞刀 mysql注入点拿shell & UDF提权教程
    [视频]K8飞刀无代码编程之生成EXP
    [视频]K8飞刀 exploit管理功能 演示教程
    [视频]K8飞刀 Discuz! X 系列(1.5 2.5 3.x)产品升级漏洞GetShell教程
    [视频]K8飞刀 WordPress XSS添加管理员 & GetShell 教程
    [视频]K8飞刀 HackerIE自动检测网站注入教程
    [视频]K8飞刀 shellcode loader演示教程
    [视频]K8飞刀 ms15022 office漏洞演示动画
  • 原文地址:https://www.cnblogs.com/punnpkin/p/13583411.html
Copyright © 2020-2023  润新知