• 单例模式Singleton


    单例模式可以说是简单又复杂的一种设计模式!

    单例就是对象只创建一个实例,并且提供一个全局的访问。但是说单例模式是复杂的设计模式也一点没错,因为涉及到DCL双锁检测(double checked locking)的讨论、涉及到多个

    类加载器(ClassLoader)协同时、涉及到跨JVM(集群、远程EJB等)时、涉及到单例对象被销毁后重建等!那么这也就不是一个简单的设计模式了!首先,我创建一个简单的单例类吧!

    package com.taobao.design;
    
    import java.io.Serializable;
    
    /**
     * 单例模式:创建型 
     */
    public class SingletonA {
        private static SingletonA instance = null;
        
        public static SingletonA getInstance()
        {
            if(instance==null){                        //line1
                instance = new  SingletonA();        //line2
            }
            return instance;
        }
    }
    /**
     * 当多线程时,如果一个线程执行到line1时,另一个线程刚刚执行完line2,那么线程1就会再去new一个对象,
     * 所以上面这种情况就有可能new出两个对象那么哪个才是我们需要的对象呢?为了防止这种情况发生,那么我
     * 把getInstance方法改成同步的!
     */
    class SingletonB {
        private static SingletonB instance = null;
        
        public synchronized static SingletonB getInstance()
        {
            if(instance==null){
                instance = new  SingletonB();
            }
            return instance;
        }
    }
    /**
     * 好!这下问题又来了!同步问题是解决了!什么问题呢!每次去调用getInstance方法时,都会有很大的性能
     * 问题,比如当两个线程现时执行到getInstance方法时,那其中某个线程肯定要等另一个线程执行完才能执行
     * ,所以至 少在至少耗时比例上存在很大性能问题的!接下来,把同步方法情改成同步代码块,在同步之前,
     * 做一下判断,双重锁定检查(DCL),这样应该解决了耗时问题了!但是总的说来一个单例这样是不上太复杂了
     */
    class SingletonC{
        private static SingletonC instance = null;
        
        public static SingletonC getInstance()
        {
            if(instance==null){
                synchronized(SingletonC.class){
                    if(instance==null){
                        instance = new  SingletonC();
                    }
                }
            }
            return instance;
        }
    }
    /**
     * 返璞归真,一个类在一个ClassLoader中只会被初始化一次,那我在初始化时就把对象new出来不就可以了吗?
     * 哈哈 !原来这么简单!
     */
    class SingletonD{
        private static SingletonD instance = new SingletonD();
        
        public static SingletonD getInstance(){
            return  instance;
        }
    }
    /**
     * 但是这样还存在一个问题,什么问题呢?上面这总是属于‘饿汉式’的创建方式,如果说要在创建之前做一些操作
     * ,比如读取配置文件,或者创建的时候必须传递某个参数给它,那该怎么办啊?ok,那我写个内部类用来创建对
     * 象,这样应该可以了吧!但是创建对象主要是通过1、new对象  2、反射构造单例对象  3、序列化构造单例,为了
     * 防止这样创建对象,那我还要加两个方法SingletonE()和readResolve(),ok,现在应该基本满足需求了吧!
     */
    class SingletonE implements Serializable{
        
        private static class Singleton{
            static final SingletonE instance = new SingletonE();
        }
        
        private static SingletonE getInstance(){
            return Singleton.instance;
        }
        //防止new 
        private SingletonE(){}
        //防止通过反序列化得到对象
        private Object readResolve() {  
            return getInstance();  
        }
        
    }

    总结:具体该如果创建单例,当然还是看情况而定,没有哪种创建方法是万能的!

  • 相关阅读:
    HDU 2100 LoveKey
    HDU 2111 Saving HDU
    HDU 2132 An easy problem
    PAT 甲级 1081 Rational Sum (数据不严谨 点名批评)
    LWIP内存管理
    LWIP带UCOS操作系统移植
    LWIP协议栈2-
    LWIP协议栈1
    掌握所有IO口的外部中断
    熟悉相关电路,控制I/O口,且配置相关参数,LED,光敏,74LS164数码管
  • 原文地址:https://www.cnblogs.com/hnhcc39/p/2586453.html
Copyright © 2020-2023  润新知