zoukankan      html  css  js  c++  java
  • 单例模式几种安全的实现

    单例的应用场景:

    需要频繁的创建和销毁对象的、创建对象时耗时过多或者消耗资源过多但是又经常用到的对象、工具类对象或数据库或文件的对象。

    当对象含有可改变的状态时(更精确的说就是在实际应用中该状态会改变),则用多例。

    一、懒汉式,线程安全的实现

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

    这虽然是线程安全的,但是效率低。还有一些比较常犯的错误,不加同步限制的,不做举例。

    二、饿汉式,线程安全

    1.构造器私有化

    2.类的内部创建对象

    3.像外部暴露一个静态的公共方法。getInstance

    优点:在类装载的时候就完成了实例化。避免了线程同步问题。

    缺点:没有达到Lazy Loading(懒加载)的效果,如果从来没使用过这个类,就会造成内存的浪费。

    public class Singleton{
      //类加载时就初始化
      private static final Singleton instance = new Singleton();

      private Singleton(){}

      public static Singleton getInstance(){
        return instance;
      }
    }

    但是要是明确要求是需要懒加载的,这个就不行的

    第二种写法,在类的静态代码块中创建实例:

    public class Singleton {
        //1.构造函数私有化
        private Singleton() {
    
        }
    
        //2.在本类的内部创建对象实例
        private static Singleton instance;
    
        static {
            instance = new Singleton();
        }
    
        //3.提供静态方法,返回实例对象
        public static Singleton getInstance() {
            return instance;
        }
    }

    三、静态内部类

    我比较倾向于使用静态内部类的方法,这种方法也是《Effective Java》上所推荐的。

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

     

    四、枚举

    用枚举写单例实在太简单了!这也是它最大的优点。下面这段代码就是声明枚举实例的通常做法。

    public enum EasySingleton{
    INSTANCE;
    }

    创建enum时,编译器会自动为我们生成一个继承自java.lang.Enum的类,我们上面的enum可以简单看作:

    class Type extends Enum{
        public static final Type A;
        public static final Type B;
        ...
    }

     demo:

    public enum SingleEnum {
        INSTANCE;
        private static String[] strings = {"1", "2"};
        public String[] getStrings() {
            return strings;
        }
    }

    五、双重检测

    //双重检查
    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; } }

    这个代码只在第一次,两个线程不能同时执行synchronized方法,但是,后面install不为空后,instance == null就直接pass掉了。volatile的作用理解是instance = new Singleton立即到内存中生效。

  • 相关阅读:
    Finance_Time-Series-Analysis-with-app-in-R
    Linear_algebra_06_二次型
    Linear_algebra_05_相似对角形
    病理学
    S&p_14_参数的假设检验
    S&p_13_参数区间估计
    Finance_Analysis-of-Financial-Time-Series
    817. Linked List Components
    811. Subdomain Visit Count
    807. Max Increase to Keep City Skyline
  • 原文地址:https://www.cnblogs.com/chenmz1995/p/10487026.html
Copyright © 2011-2022 走看看