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的时候才进行同步,保证了性能。

  • 相关阅读:
    CentOS 配置epel源
    phpstudy + dvws
    被动信息收集
    Mysql 通过information_schema爆库,爆表,爆字段
    油猴百度云
    浏览器如何弹出下载框
    Ubuntu更新源
    关于cookie
    monitor
    分享一个自制的计算子网划分的小工具
  • 原文地址:https://www.cnblogs.com/byghui/p/3057870.html
Copyright © 2011-2022 走看看