zoukankan      html  css  js  c++  java
  • 设计模式-单例模式

    单例模式

    定义:用于保证一个类仅有一个实例,并提供别的类访问它的方法。

    使用场景:需要控制实例只能有一个、节省资源的时候。

    常用的创建单例模式的方法有6种。

    1. 懒汉式

    线程不安全、延迟初始化

    public class Singleton {
    
        private Singleton(){}
        
        private static Singleton singleton;
        
        public static Singleton getInstance(){
            if(singleton==null){
                singleton=new Singleton();
            }
            return singleton;
        }
    }
    
    1. 懒汉式(加锁)

    线程安全、延迟初始化

    public class Singleton {
    
        private Singleton(){}
    
        private static Singleton singleton;
    
        public static synchronized Singleton getInstance(){
            if(singleton==null){
                singleton=new Singleton();
            }
            return singleton;
        }
    }
    
    1. 饿汉式

    线程安全、非延迟初始化

    public class Singleton {
    
        private Singleton(){}
    
        private static Singleton singleton=new Singleton();
    
        public static  Singleton getInstance(){
            return singleton;
        }
    }
    
    1. 双检锁(double-check)

    线程安全、延迟初始化

    public class Singleton {
    
        private Singleton(){}
    
        private static Singleton singleton;
    
        public static  Singleton getInstance(){
            if(singleton==null){
                synchronized (Singleton.class){
                    if(singleton==null){
                        singleton=new Singleton();
                    }
                }
            }
            return singleton;
        }
    }
    
    1. 静态内部类

    线程安全、延迟初始化

    public class Singleton {
    
    
        private Singleton() {
        }
    
        private static class SingletonHolder {
            private static final Singleton instance = new Singleton();
        }
    
        public static final Singleton getInstance() {
            return SingletonHolder.instance;
        }
    }
    
    1. 枚举

    线程安全、非延迟初始化

    这种方式实现简单,并且不仅避免多线程同步问题,而且防止反序列化重新创建新对象。

    public enum  Singleton {
        INSTANCE;
    }
    

    单例中的bug;反射创建和反序列化创建。

      public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
            Singleton instance1 = Singleton.getInstance();
            Constructor<Singleton> declaredConstructor = Singleton.class.getDeclaredConstructor(null);
            //跳过权限检查,加载私有构造器
            declaredConstructor.setAccessible(true);
            Singleton instance2 = declaredConstructor.newInstance();
            System.out.println(instance1);   //com.mmc.springbootstudy.parteen.singleton.Singleton@5ce65a89
            System.out.println(instance2);   //com.mmc.springbootstudy.parteen.singleton.Singleton@25f38edc
        }
    

    如何避免反射创建呢?

    以静态内部类为例,在构造方法中抛异常

    如何避免反序列化?

    定义一个readResolve()方法,直接返回指定对象

    public class Singleton implements Serializable {
        private static class SingletonHolder {
            private static final Singleton INSTANCE = new Singleton();
        }
        private Singleton (){
            if(SingletonHolder.INSTANCE!=null){
                throw new RuntimeException();
            }
        }
        public static final Singleton getInstance() {
            return SingletonHolder.INSTANCE;
        }
    
        //防止反序列化
        private Object readResolve(){
            return getInstance();
        }
    }
    

    一般来说我们使用饿汉方式就行了,如果明确要求要延迟初始化,就使用静态内部类的方式。

    返回目录

    书山有路勤为径,学海无涯苦作舟
  • 相关阅读:
    数据驱动ddt简单使用
    html-testRunner在unittest测试套件中的使用
    Python设计模式----3.单例模式
    Python设计模式----2.工厂模式
    Python设计模式----1.简单工厂模式
    在小程序中对图片进行缩放时发生的问题记录
    将项目发布到Maven中央仓库的不完整纪要
    虚机的SQL Server空间占满之后进行释放的一些操作
    jdk8环境下,添加重复注解的美好体验
    使用transient关键字解决ehcache序列化错误
  • 原文地址:https://www.cnblogs.com/javammc/p/14938637.html
Copyright © 2011-2022 走看看