单例模式

来源:互联网 发布:c语言实型数据 编辑:程序博客网 时间:2024/04/27 13:10

单例模式,独一无二的对象,提供一个全局访问点。

        1. 非多线程下使用。

/** * 单例模式,提供全局访问点 *  * @author fuzhengchao *  */public class Singleton {private static Singleton uniqueInstance;private Singleton() {// 一些初始化操作}public static Singleton getInstance() {if (null == uniqueInstance) {uniqueInstance = new Singleton();}return uniqueInstance;}}

      由getInstance()方法的实现我们可以看出,单例模式还有延迟实例化的作用,在第一次需要的时候才创建对象。


      但是这种实现方法在多线程的时候就有问题了,当多个线程同时进入if (null == uniqueInstance) 和uniqueInstance = new Singleton();

      之间时,就会创建多个对象,这就违背了单例模式的设计初衷了。


 2. 多线程下单例模式的实现。

     2.1 如果多线程线程数不是很多,程序对性能要求不是很高,我们可以这样设计:

/** * 单例模式,提供全局访问点 *  * @author fuzhengchao *  */public class Singleton {private static Singleton uniqueInstance;private Singleton() {// 一些初始化操作}// 加锁public static synchronized Singleton getInstance() {if (null == uniqueInstance) {uniqueInstance = new Singleton();}return uniqueInstance;}}

       把getInstance()加锁,这样就能保证多个线程不能同时进入创建多个对象了。 但为什么这样做会影响程序性能呢?如果线程过多,每次调用getInstance()方法时,只能一个线程一个线程进入,那么这里就会造成很多线程等待同步,从而影响性能。

     2.2 使用“急切”创建实例,而不用延迟实例化的做法。

         

/** * 单例模式,提供全局访问点 *  * @author fuzhengchao *  */public class Singleton {private static Singleton uniqueInstance = new Singleton();private Singleton() {// 一些初始化操作}public static Singleton getInstance() {return uniqueInstance;}}

        从上面的代码我们可以看出,我们取消了加锁操作,直接在静态初始化中创建了对象,我们依赖JVM在加载这个类是创建了唯一的单例,后面不会在创建了。这样再多的线        程同时操作也不会出现等待同步影响性能了,但是这样新问题又出现了,我们的单例不能延迟实例化了,程序一开始就创建了这个对象一直到程序退出,如果中间运用这个         单例在程序很靠后,或则很少情况下,这样就比较浪费资源了。

       2.3 用“双重检测加锁”,在getInstance()中减少使用同步

/** * 单例模式,提供全局访问点 *  * @author fuzhengchao *  */public class Singleton {private static Singleton uniqueInstance;private Singleton() {// 一些初始化操作}// 加锁public static Singleton getInstance() {if (null == uniqueInstance) {synchronized ((Singleton.class)) {if (null == uniqueInstance) {uniqueInstance = new Singleton();}}}return uniqueInstance;}}

        这样只有在第一次创建对象时,多个线程同时进入第一个null == uniqueInstance和synchronizede()之间时,一个线程进去创建对象,其它线程获取对象会出现等待同步。只要对象一旦创建成功,后续的线程都直接在第一个null == unigueInstance 退出,后面就不会有性能问题了。但是已经进入null == uniqueInstance 和synchronized之间的线程还得等待同步。


原创粉丝点击