zoukankan      html  css  js  c++  java
  • 如何写出一个性能优化的单例模式

    单例模型是面试当中最常见的一种设计模式,它是一种对象创建模式,用于产生一个对象的具体实例,可以确保系统中一个类只产生一个实例。

    简而言之,单例模式可以带来两个好处:

    1、对于频繁使用到的对象,可以节省反复创建对象花费的时间;

    2、减少对象的实例化操作,故而可以降低系统内存的使用频率;

    根据以上两点,可看出使用单例模式能够有效地改善系统的性能。

    最常见的单例模式有饿汉模式与懒汉模式。

    1、饿汉模式长这样的:

     1 public class Singleton{
     2  
     3   private Singleton(){}
     4   
     5   private static final Singleton instance=new Singleton();
     6 
     7   public static Singleton getInstance(){
     8   
     9   return instance;
    10   }
    11 }

    这种单例模式非常简单,唯一不足的是,无法对instance实例做延迟加载,由于instance成员变量是static定义的,因此JVM在加载单例类时,单例对象就会被建立,如果这个单例类在系统中还包含了其他的静态方法,每次通过这个单例类去调用其他的静态方法时,就会加载被static定义的成员变量,也就是加载了private static final Singleton instance=new Singleton(),故而就会创建一个Singleton实例出来,可以通过一个例子来进行说明:

     1 public class Singleton{
     2 
     3     private Singleton(){
     4 
     5         System.out.println("创建了一个单例!");
     6     }
     7 
     8     private static final Singleton instance=new Singleton();
     9 
    10     public static Singleton getInstance(){
    11 
    12         return instance;
    13     }
    14 
    15     public static void Test(){
    16 
    17         System.out.println("调用了这个方法!");
    18     }
    19 
    20 }

    打印出这样的信息:

     

    由此可见,饿汉模式因为没有延迟加载机制,存在着对象容易被创建的问题,这将会影响系统在调用相关函数时的反应速度,可以加入延迟加载机制来解决这个问题。

    加了延迟机制的单例模式,就成了我们常见的懒汉模式了,但这里加了同步安全机制:

     1 public class SingletonSyn{
     2 
     3 private SingletonSyn(){
     4     System.out.println("创建了一个线程安全的懒汉单例!");
     5 }
     6 
     7     private static  SingletonSyn instance=null;
     8 
     9     public static synchronized SingletonSyn getInstance() {
    10     if (instance == null)
    11         instance = new SingletonSyn();
    12         return instance;
    13 
    14     }
    15 }

    这里需注意的地方是:getInstance()方法必须是同步的,否则在多线程环境下,当线程1正新建单例时,完成操作赋值时,线程2可能判断instance为null,故线程2也将启动新建单例程序,这样就会导致多个实例被创建,对性能的影响将会加剧,故加synchronized做同步是必须的。

    可谓成也萧何败也萧何,虽然加上了同步关键字synchronized 可以解决同步问题,但因在多线程的环境下,它的性能消耗将远远大于第一种饿汉模式。

    基于前面两种单例模式,可以对它做进一步的改进:

     1 public class Singleton{
     2  
     3   private Singleton(){System.out.println("创建了一个基于内部类的单例模式!");}
     4   
     5   private static class SingletonHolder{
     6      private static Singelton instance=new Singleton();
     7 
     8 }
     9 
    10   public static  Singleton getInstance(){
    11  
    12   return SingletonHolder.instance;
    13  
    14    }
    15 }

    上面的例子使用内部类来维护单例的实例,当Singleton被加载时,其内部类并不会被初始化,故可以确保当Singleton类被载入JVM时,不会初始化单例类,只有当getInstance()被调用时,才会加载内部类SingletonHolder,从而实例化单例类instance。同时,由于实例的建立是在类加载时才完成的,故天生对多线程友好,getInstance方法也无需使用同步synchronized,可见,使用内部类方式实现单例,既可以做到延迟加载,也不必使用同步关键字,是一种比较完善的实现。

    当然,若需更加完善单例模式的设计,还有更优的方式,感兴趣的伙伴可以继续深入进行一个探讨。

    我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2lfj12z61ny88

  • 相关阅读:
    USACO 3.3 A Game
    USACO 3.3 Camelot
    USACO 3.3 Shopping Offers
    USACO 3.3 TEXT Eulerian Tour中的Cows on Parade一点理解
    USACO 3.3 Riding the Fences
    USACO 3.2 Magic Squares
    USACO 3.2 Stringsobits
    USACO 3.2 Factorials
    USACO 3.2 Contact
    USACO 3.1 Humble Numbers
  • 原文地址:https://www.cnblogs.com/zhujiqian/p/11337255.html
Copyright © 2011-2022 走看看