zoukankan      html  css  js  c++  java
  • 初学设计模式【7】单例模式——sington

      有一些对象其实我们只需要一个,比如:线程池、缓存、充当显卡等设备的驱动程序的对象。这类对象只能有一个实例,否则会出现很多问题,资源消耗过多、数据不一致等。

    定义

      确保一个类只有一个实例,并提供一个全局的访问点。

    类图

      

    说明:1.一个private static的Singleton实例变量instance.

       2.一个public static 的getInstance方法,返回instance。

       3.一个私有构造方法

    经典实现

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

     分析:为了保证类只有一个实例,Singleton类的构造方法需为private的这样外界不能通过new直接实例化对象,而只能通过Singleton提供的全局访问点getinstance方法获得,这样就保证了类对象的惟一性。

    问题:这样写看上去很完美,实事上是这样吗?可,现实是残酷的,呵呵。

    假设,我们有两个线程A,B同时访问上面的代码。假设A线程执行完if(instance == null)后时间片用完,然后B线程来访问上面的代码,假设B线程执行完了instance = new Singleton();即现在Singleton已经有了一个实例化对象。然后B时间片用完A线程回来接着执行,A线程要执行instance = new Singleton();这样就会带来一个问题,Singleton被实例化了两次。显然,这不是我们想要的,应该怎么解决呢?

    解决方案:

      我们知道上面的问题是由线程同步问题造成的,那么我们可以直接将getinstance方法加上线程同步锁既可,如下:

    1 public static synchronized Singleton getInstance() {
    2         if (instance == null) {
    3             instance = new Singleton();
    4         }
    5         return instance;
    6     }

     新的问题:这样的确是没同步问题了,但线程同步会造成性能的降低,并且对于我们这种情况,我们实际上只需要在第一次进行同步(instance为null时),以后都不需要进行同步了,可我们上面的代码每次执行都会进行同步,显然这是不合理的,那应该怎么解决呢?

    方案A:提前初始化instance。

      如果我们的程序总是创建并使用单例实例,或者在创建和运行方面的负担不太繁重,你可以提前实例化instance,如下所示:

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

     利用此方法,我们可以在JVM加载这个类时就创建此惟一的对象。JVM保证在任何线程访问instance之前,一定先创建此实例。

     方案B:双重检查锁   

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

     通过此方法既可保证只在instance为null的时候才进行同步,保证了性能。

  • 相关阅读:
    优先队列
    Problem W UVA 662 二十三 Fast Food
    UVA 607 二十二 Scheduling Lectures
    UVA 590 二十一 Always on the run
    UVA 442 二十 Matrix Chain Multiplication
    UVA 437 十九 The Tower of Babylon
    UVA 10254 十八 The Priest Mathematician
    UVA 10453 十七 Make Palindrome
    UVA 10163 十六 Storage Keepers
    UVA 1252 十五 Twenty Questions
  • 原文地址:https://www.cnblogs.com/byghui/p/3057870.html
Copyright © 2011-2022 走看看