zoukankan      html  css  js  c++  java
  • 【7.13】单例模式(Singleton)的用法和用处以及破解单例

    1):用处  

      是一种创建者模式,只生成一个实例对象,具有全局唯一性,当一个对象的产生需要比较多的资源时, 如读取配置(如数据库连接池、Spring中, 一个Component就只有一个实例Java-Web中, 一个Servlet类只有一个实例等), 产生其他依赖对象, 则可以通过在应用启动时直接产生一个单例对象, 然后永久驻留内存的方式来解决

    2):写法

        private化构造函数

        private Singleton实例

        提供一个public的获取实例的方法

      主要有五种实现方式,懒汉式(延迟加载,使用时初始化),饿汉式(声明时初始化),双重检查,静态内部类,枚举

      1:饿汉式

        当多个线程同时访问,都没有实例化的时候,该单例模式将被破坏

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

      2:懒汉式

        线程安全,但是效率低下,多数情况是不需要加锁的

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

      3:双重检查

        

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

      4:匿名内部类

        内部类不会在类的外部被调用,使用当调用暴露的getInstance()方法是调用,由于java虚拟机的classLoaded机制,不会被重复调用使用

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

      5:枚举类

        枚举类的构造方法被private,不能创建枚举对象,所以保证了线程安全

    public enum Singleton {
        INSTANCE;
        public String error(){
            return "error";
        }
    } 

    3)破坏

      除了枚举,都可以用反射来破坏单例模式,可以通过反射来获取实例对象

    import java.lang.reflect.Constructor;
    public class TestCase {
        public void testBreak() throws Exception {
            Class<Singleton> clazz = (Class<Singleton>) Class.forName("Singleton");
            Constructor<Singleton> constructor = clazz.getDeclaredConstructor();
            constructor.setAccessible(true);
            Singleton instance1 = constructor.newInstance();
            Singleton instance2 = constructor.newInstance();
            System.out.println("singleton? " + (instance1 == instance2));
        }
        public static void main(String[] args) throws Exception{
            new TestCase().testBreak();
        }
    }  

        

  • 相关阅读:
    多线程与MySQL(十)
    多进程与多线程(九)
    异常处理与网络编程(八)
    面向对象,绑定方法与异常处理(七)
    模块与对象(六)
    包与模块(五)
    迭代器与函数Python学习(四)
    函数与装饰器Python学习(三)
    数据库
    并发编程
  • 原文地址:https://www.cnblogs.com/yuwenhui/p/7162621.html
Copyright © 2011-2022 走看看