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

    /**
    * 单例模式(单子模式):确保某个类只有一个实例,
    * 而且自行实例化并向整个系统提供这个实例的单例模式;
    * 适用在有真正“单一实例”需求时;
    *
    一个类能否做成单例取决于 在应用中如果有两个或者两个以上的实例是否会引起错误(包括程序错误和逻辑错误)
    好处:节约内存空间,减少无谓的GC消耗

    * 下面介绍5种写法:
    * 第一种方法:多线程中不能正常工作;
    * 1.声明一个私有的静态的当前类的对象;
    * 2.让构造器私有;
    * 3.声明一个公共的静态返回自己的方法;
    * 4.在该方法内部将当前类的对象自行实例化;

    * 第二种方法:适用多线程,但效率低;
    * 同第一种方法,唯一的不同就是在声明方法时加一个“synchronized”表示同步的关键字;

    * 第三种方法:是第二种方法的升级版,又称双重检查锁定版;
    * 1.声明一个私有的静态的当前类的对象,但要加上volatail类型修饰符;
    * 2.让构造器私有;
    * 3.声明一个公共的静态返回自己的方法;
    * 4.在该方法内部将当前类的对象自行实例化,但用synchronized关键字进行锁定当前类;

    (推荐)第四种方法:应用内部类实现,适用于多线程,采用的是classloader机制保证实例化时只有一个线程,是比较安全的单子模式,但编写有点麻烦;
    * 1.编写一个私有的静态的内部类,在类中实现“单一实例”(是私有的静态的常量);
    * 2.让构造器私有;
    * 3.声明一个公共的静态返回自己的方法;
    * 4.在该方法的内部返回内部类中的对象常量;
    * 第五种方法:是第四种方法类似;
    * 1.直接初始化单例的实例;
    * 2.让构造器私有;
    * 3.在该方法内部返回实例;
    */
    第一种方法:
    /**
     * 在不考虑并发访问的情况下标准的单例模式的构造方式
     */
    public class Singleton1 {
        //这里必须用staic,因确保某个类只有一个实例,也是为了在getInstance()这个静态方法中使用它;
        private static Singleton1 s;
        
        //首先将构造函数私有;使在在类的外部不能被实例化;
        private Singleton1() {
        }
    //这里必须用staic,因为无法通过动态的实例化对象调用,只能是静态的; public static Singleton1 getInstance() { if(s == null) { s = new Singleton1(); } return s; } }

     第二种方法:

    /**
     * 考虑并发的情况了,我们最容易想到的方式应该是下面这样的方式,直接将整个方法同步 (synchronized)
     */
    public class Singleton2 {
        private static Singleton2 s;
        
        private Singleton2() {
        }
    
        public static synchronized Singleton2 getInstance() {
            if(s == null) {
                s = new Singleton2();
            }
            return s;
        }
    
    }

     第三种方法:

    /**
     * 很多教科书中标准的单例模式版本,也称为双重加锁,但在其基础上又使用valatile类型修饰符。故暂且称为:双重锁定检查版的单例
     *
     * 加volatile关键字的好处:
     *           如果深入到JVM中去探索不加volatile的双重加锁的代码,它是有可能(注意,只是有可能)发生问题的。
           因为虚拟机在执行创建实例的这一步操作的时候,其实是分了好几步去进行的,也就是说创建一个新的对象并非是原子性操作。
           如果按照正常顺序执行,那就没有问题;怕就怕JVM不按常理出牌,进行指令的调优,那就可能会出问题了;
           因此在某些特定的情况下是会造成莫名的错误;
     */
    public class Singleton3 {
        /*
         * volatile是一个类型修饰符;它是被设计用来修饰被不同线程访问和修改的变量。
         * 如果不加volatile,基本上会导致这样的结果:要么无法编写多线程,要么编译器失去大量优化的机会;
         * 它的作用:作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值;
         *        简单来说就是防止编译器对代码进行优化;
         * 一般适用于多线程并行开发;
         */
        private static volatile Singleton3 s; //第一重锁定,用volatile关键字;
        
        private Singleton3() {
        }
        
        public static Singleton3 getInstance() {
            if(s == null) {
                synchronized (Singleton3.class) { //第二种锁定,用synchronized关键字;
                    if(s == null) {
                        s = new Singleton3();
                    }
                }
            }
            return s;
        }
        
    }

     第四种方法:

    /**
     *   最为推荐的单例模式写法:使用静态的内部类作为单例
     */
    public class Singleton4 {
        //用一个私有的静态的内部类来实现单例模式;
        private static class SingletonHolder {
            //是私有的静态常量;
            private static final Singleton4 INSTANCE = new Singleton4();
        }
        
        private Singleton4() {
        }
        
        public static Singleton4 getInstance() {
            return SingletonHolder.INSTANCE;
        }
    }

     第五种方法:

    package com.singleton;
    
    /**
     * 俗称“饿汉式加载”的单例模式(其实跟Singleton3内部类的方式类似)
     * 注:
     * 这种方式最主要的缺点就是一旦我访问了Singleton5类的任何其他的静态域,
     * 就会造成实例的初始化,而事实是可能我们从始至终就没有使用这个实例,造成内存的浪费。
     *   不过在有些时候,直接初始化单例的实例也无伤大雅,对项目几乎没什么影响
     */
    
    public class Singleton5 {
    
        private static Singleton5 singleton = new Singleton5();
    
        private Singleton5(){}
    
        public static Singleton5 getInstance(){
            return singleton;
        }
    
    }
  • 相关阅读:
    P2572 [SCOI2010]序列操作
    P2787 语文1(chin1)- 理理思维
    P1835 素数密度_NOI导刊2011提高(04)
    P3942 将军令
    P1273 有线电视网
    U45490 还没想好名字的题Ⅱ
    U40620 还没想好名字的题
    P4644 [Usaco2005 Dec]Cleaning Shifts 清理牛棚
    P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm
    T51071 Tony到死都想不出の数学题
  • 原文地址:https://www.cnblogs.com/zhaojinxin/p/6666214.html
Copyright © 2011-2022 走看看