zoukankan      html  css  js  c++  java
  • 单例模式总结

    Reference

    [1] http://jiangzhengjun.iteye.com/blog/652440

    [2] http://blog.sina.com.cn/s/blog_6ee97c580100opvp.html

    [3] http://javarevisited.blogspot.co.uk/2014/05/double-checked-locking-on-singleton-in-java.html

    [4] https://www.hollischuang.com/archives/2498

    单例类的特点:
    1、单例类在整个系统中只能有一个实例
    2、单例类必须自己创建自己的实例
    3、单例类必须系统中其他对象提供这个实例

    单例类的优点:

    (1) 控制资源的使用,通过线程同步来控制资源的并发访问。
    (2)控制实例的产生数量,达到节约资源的目的。
    (3)作为通信的媒介,数据共享。他可以在不建立直接关联的条件下,让多个不相关的两个线程或者多个进程之间实现通信。

    单例类实用举例:Windows的任务管理器,打不开两个。 网站的计数器,不然很难实现同步。   数据库连接池的设计

    饿汉模式(非延迟加载)

    在类加载时就立即创建对象。优点时没有加锁,执行效率高。缺点是类加载时就初始化,浪费内存。

    public class SingletonOne {
      //Create instance when the class load.
      private static final SingletonOne m_instance = new SingletonOne();
      //此处写成私有方法可以防止用户在外面用new方法来产生。
      private SingletonOne(){}
    
      public static SingletonOne getInstance(){
         return m_instance;
      }
    }

    懒汉模式(同步延迟加载)

    Lazy Load, 只在外部对象第一次请求实例的时候才会去创建,优点是第一次调用才会初始化,避免内存浪费。缺点是必须加锁synchronized才能保证单例。

    public class SingletonTwo {
      private static SingletonTwo m_getInstance = null;
    
      //此处写成私有方法可以防止用户在外面用new方法来产生。
      private SingletonTwo(){
      
      }
      //synchronized可以保证线程安全
      public synchronized static SingletonTwo getInstance(){
         //When invoke the instance then create instance.
         if (m_getInstance == null){
            m_getInstance = new SingletonTwo();
         }
         return m_getInstance;
      }
    }

    双重检测同步延迟加载 

    为处理原版同步延迟加载方式瓶颈问题,我们需要对 instance 进行第二次检查,目的是避开过多的同步(因为这里的同步只需在第一次创建实例时才同步,一旦创建成功,以后获取实例时就不需要同获取锁了)。

    所谓双重检查加锁机制,指的是:并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法过后,先检查实例是否存在,如果不存在才进入下面的同步块,这是第一重检查。进入同步块过后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。这样一来,就只需要同步一次了,从而减少了多次在同步情况下进行判断所浪费的时间。

     双重检查加锁机制的实现会使用一个关键字volatile,它的意思是:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。
    注意:在Java1.4及以前版本中,很多JVM对于volatile关键字的实现有问题(no happens-brfore),会导致双重检查加锁的失败,因此双重检查加锁的机制只能用在Java5及以上的版本。

    public class Singleton {
        private volatile static Singleton instance = null;
        private Singleton(){
        }
        public static  Singleton getInstance(){
            //先检查实例是否存在,如果不存在才进入下面的同步块
            if(instance == null){
                //同步块,线程安全的创建实例
                synchronized(Singleton.class){
                    //再次检查实例是否存在,如果不存在才真的创建实例
                    if(instance == null){
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }

    改进型懒汉模式

    内部类只有在外部类被调用才加载,产生SINGLETON实例,又不用加锁,此模式有上述俩模式的优点,屏蔽了他们的缺点,是比两者都好的单例模式。

    public class Singleton{
        private Singleton(){}
        public static Singleton getInstance(){ return Holder.SINGLETON;}
        private static class Holder{//内部类
            private static final Singleton SINGLETON= new Singleton();
        }
    }

    ENUM单例模式

     线程安全而且代码最为简单

    public enum Singleton {  
        INSTANCE;  
        public void whateverMethod() {  
        }  
    } 
  • 相关阅读:
    画图工具Graphviz安装配置
    转:完善eclipse+pdt作php开发中的代码提示能力
    转:SVN 出现This client is too old to work with working copy...错误
    Codeforces Round #260 (Div. 2)C. Boredom(dp)
    three.js 源代码凝视(十四)Math/Sphere.js
    android项目中刷新activity界面
    中科燕园GIS外包---地铁GIS项目
    华为HCNA教程(笔记)
    HapiJS开发手冊
    《Java并发编程实战》第十四章 构建自己定义的同步工具 读书笔记
  • 原文地址:https://www.cnblogs.com/codingforum/p/6943176.html
Copyright © 2011-2022 走看看