码迷,mamicode.com
首页 > 其他好文 > 详细

设计模式之单例模式

时间:2015-08-15 09:01:49      阅读:104      评论:0      收藏:0      [点我收藏+]

标签:

  单例模式(Singleton) —— 对象创建型模式

  本文记录单例模式从设计理念的简单到复杂,从运行效果的低效到高效,各种不同实现方式。涉及到多线程和JVM。

定义

  保证一个类仅有一个实例,并提供一个访问它的全局访问点。

  The Singleton Pattern ensures a class has only one instance, and provides a gloable point of access to it.

类图

  技术分享

实现

实现一:最简单,线程不安全。 

/**
 * @description 最简单的实现,线程不安全。
 * @author michael
 */
public class Singleton {
    
    private static Singleton uniqueInstance;
    
    //Other useful Singleton data...
    
    /**
     * 构造器私有化
     */
    private Singleton() {
        
    }
    
    /**
     * @description 抽象工程方法(static factory),获得该类唯一实例。
     * @return 唯一实例
     */
    public static Singleton getInstance() {
        if(null == uniqueInstance) {
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }
    
    //Other useful Singleton methods...

}

实现二:同步方法

使用synchronized关键字,同步getInstance()方法,确保任意时刻只有一个线程可以访问该方法。线程安全,效率低。 

/**
 * @description 线程安全,效率低。
 * @author michael
 */
public class Singleton {
    
    private static Singleton uniqueSingleton;
    
    //Other useful Singleton data...
    
    /**
     * 构造器私有化
     */
    private Singleton() {
        
    }
    
    /**
     * @description 同步方法,线程安全,效率低。
     * @return 唯一实例
     */
    public static synchronized Singleton getInstance() {
        if(uniqueSingleton == null) {
            uniqueSingleton = new Singleton();
        }
        return uniqueSingleton;
    }

    //Other useful Singleton methods...
    
}

实现三:饿汉式

先于方法调用前创建实例,静态初始化变量。依赖于JVM的实现,虚拟机要确保在任何线程访问静态变量uniqueSingleton之前创建好实例。 

/**
 * @description move to an eagerly created instance rather than a lazily created one.
 * @author michael
 */
public class Singleton {
    
    private static Singleton uniqueSingleton = new Singleton();
    
    //Other useful Singleton data...
    
    /**
     * 构造器私有化
     */
    private Singleton() {
        
    }
    
    /**
     * @description eagerly created
     * @return 唯一实例
     */
    public static synchronized Singleton getInstance() {
        return uniqueSingleton;
    }

    //Other useful Singleton methods...
    
}

实现四:双检测

使用volatile关键字修饰变量,确保多线程访问修改正确。双检测,只有在第一次调用getInstance()才会同步类。版本要求:JDK1.5或以上。

解释下为什么需要双重检测,假设此时uniqueSingleton == null,两个线程同时调用getInstance()方法,由于uniqueSingleton还未创建,

if条件满足,两个线程都会进入if语句内部。但是下一步只有一个线程会拿到锁,进入到同步代码块,此时再次检测依然为空,创建实例,

释放锁,并返回实例。当另一个线程获得锁进入同步代码块时,实例已创建,释放锁返回实例。这是双重检测的情况,如果不在同步块内二次检测,

同样两个线程同时访问getInstance()方法,在if语句内,同步方法块外堵塞。获得锁的线程创建实例、释放锁并返回实例。当另一个线程获得锁执行同步代码时,

没有进行二次检测,尽管此时uniqueSingleton已经被创建,后获得锁的线程依然会再创建一个实例,违反了唯一实例的原则。 

/**
 * @description double checked
 * @author michael
 * @see 1.5
 */
public class Singleton {
    
    //volatile 多线程共享变量
    private volatile static Singleton uniqueSingleton;
    
    //Other useful Singleton data...
    
    /**
     * 构造器私有化
     */
    private Singleton() {
        
    }
    
    /**
     * @description 双检测
     * @return 唯一实例
     */
    public static synchronized Singleton getInstance() {
        if(uniqueSingleton == null) {
            //多线程 可能在这堵塞 双检测 避免重复构造
            synchronized(Singleton.class) {
                if(uniqueSingleton == null) {
                    uniqueSingleton = new Singleton(); 
                }
            }
        }
        return uniqueSingleton;
    }

    //Other useful Singleton methods...
    
}

实现五:基于JVM对实现四的改进,避免引用还未完全初始化的对象。

解释:当第一次调用getInstance()方法,执行uniqueSingle = new Singleton()这句代码,JVM可能在new Single()并未完全执行,

就已经给uniqueSingleton分配地址(uniqueSingleton != null),而此时如果另一个线程调用getInstance()方法,

就会得到还未完全初始化的uniqueSingleton的引用。实现五使用一个中间变量singleton确保uniqueSingleton的完整性。

/**
 * @description double checked
 * @author michael
 * @see since 1.5
 */
public class Singleton {
    
    //volatile 多线程共享变量
    private volatile static Singleton uniqueSingleton;
    
    //Other useful Singleton data...
    
    /**
     * 构造器私有化
     */
    private Singleton() {
        
    }
    
    /**
     * @description 双检测
     * @return 唯一实例
     */
    public static synchronized Singleton getInstance() {
        if(uniqueSingleton == null) {
            //多线程 可能在这堵塞 双检测 避免重复构造
            synchronized(Singleton.class) {
                if(uniqueSingleton == null) {
                    //avoid getting a reference to an incompletely initialized object
                    Singleton singleton = new Singleton();
                    uniqueSingleton = singleton;
                }
            }
        }
        return uniqueSingleton;
    }

    //Other useful Singleton methods...
    
}

效果

  1.对唯一实例的受控访问

  2.缩小名空间

  3.允许对操作和表示的精化

  4.允许可变数目的实例

  5.比类操作更灵活

相关模式

  很多模式可以使用单例模式实现。参见抽象工厂模式(Abstract Factory)、建造者模式(Builder),和原型模式(Prototype)。

设计模式之单例模式

标签:

原文地址:http://www.cnblogs.com/coderworld/p/design-pattern-singleton.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!