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

      简单点说,就是一个应用程序中,某个类的实例对象只有一个,你没有办法去new,因为构造器是被private修饰的,一般通过getInstance()的方法来获取它们的实例。getInstance()的返回值是一个对象的引用,并不是一个新的实例,所以不要错误的理解成多个对象。单例模式实现起来也很容易,直接看demo吧

     懒汉式写法(线程不安全)

    public class Singleton {
    
      private static Singleton singleton;
    
      private Singleton() {
      }
    
      public static Singleton getInstance() {
       if (singleton == null) {
        singleton = new Singleton();
       }
       return singleton;
      }
    }

    按照我的习惯,我恨不得写满注释,怕你们看不懂,但是这个代码实在太简单了,所以我没写任何注释,如果这几行代码你都看不明白的话,那你可以洗洗睡了,等你睡醒了再来看我的博客说不定能看懂。

    上面的是最基本的写法,也叫懒汉写法(线程不安全)下面我再公布几种单例模式的写法:

    懒汉式写法(线程安全)

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

     

    饿汉式写法

     线程安全,比较常用,但容易产生垃圾,因为一开始就初始化

    public class Singleton {  
       private static Singleton instance = new Singleton();  
       private Singleton (){}  
       public static Singleton getInstance() {  
         return instance;  
       }  
    }


    静态内部类

    public class Singleton {  
       private static class SingletonHolder {  
         private static final Singleton INSTANCE = new Singleton();  
       }  
       private Singleton (){}  
       public static final Singleton getInstance() {  
         return SingletonHolder.INSTANCE;  
       }  
    }
    只有第一次调用getInstance方法时,虚拟机才加载 SingletonHolder并初始化INSTANCE,只有一个线程可以获得对象的初始化锁,其他线程无法进行初始化,保证对象的唯一性。目前此方式是所有单例模式中最推荐的模式,但具体还是根据项目选择。
    
    

     枚举

    public enum Singleton {  
       INSTANCE;  
       public void whateverMethod() {  
       }  
    }

    这种方式是Effective Java作者Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象,可谓是很坚强的壁垒啊,不过,个人认为由于1.5中才加入enum特性,用这种方式写不免让人感觉生疏。


    双重校验锁

    public class Singleton {  
       private volatile static Singleton singleton;  
       private Singleton (){}  
       public static Singleton getSingleton() {  
       if (singleton == null) {  
           synchronized (Singleton.class) {  
           if (singleton == null) {  
               singleton = new Singleton();  
           }  
           }  
       }  
       return singleton;  
       }  
    }

    线程安全,延迟初始化。这种方式采用双锁机制,安全且在多线程情况下能保持高性能

    
    

    总结:我个人比较喜欢静态内部类写法和饿汉式写法,其实这两种写法能够应付绝大多数情况了。其他写法也可以选择,主要还是看业务需求吧。

  • 相关阅读:
    SQL中存储过程与自定义函数的区别
    内置函数
    正则表达式
    HTML发展史
    触发器
    事务
    视图
    索引的使用
    存储过程和自定义函数的区别
    游标用法
  • 原文地址:https://www.cnblogs.com/wuwuyong/p/12469773.html
Copyright © 2011-2022 走看看