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();
        }
    }
    

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

    返回目录

    书山有路勤为径,学海无涯苦作舟
  • 相关阅读:
    iSCSI又称为IPSAN
    文档类型定义DTD
    HDU 2971 Tower
    HDU 1588 Gauss Fibonacci
    URAL 1005 Stone Pile
    URAL 1003 Parity
    URAL 1002 Phone Numbers
    URAL 1007 Code Words
    HDU 3306 Another kind of Fibonacci
    FZU 1683 纪念SlingShot
  • 原文地址:https://www.cnblogs.com/javammc/p/14938637.html
Copyright © 2011-2022 走看看