单例模式

单例模式是一种最简单的设计模式,它的类图上只有一个类!尽管从类设计的角度来说它简单,但是实现上还是会遇到问题。请系好安全带,发车了!

基本介绍

单例模式确保类中只有一个实例,并向外提供一个获取该实例的接口。它常常被用来管理共享资源,例如数据库的连接、线程池、缓存等。
单例模式一般有两种表现形式:
- 饿汉模式:类加载时,进行对象的实例化
- 懒汉模式:第一次引用类时,进行对象的实例化

饿汉模式

饿汉模式的创建步骤如下:
1. 创建一个私有的静态成员变量,并进行实例化;
1. 将构造函数进行私有化,让外界无法对它进行实例化;
1. 提供一个公开返回对象实例化的静态方法。

代码如下:

public class Singleton {
    //创建一个私有的静态成员变量,并进行实例化
    private static Singleton sInstance = new Singleton();

    //将构造函数进行私有化
    private Singleton{} {
    }

    //提供一个公开返回对象实例化的静态方法
    public static Singleton getInstance() {
        return sInstance;
    }
}

懒汉模式

懒汉模式的创建步骤如下:
1. 声明一个私有的静态成员变量;
1. 将构造函数进行私有化,让外界无法对它进行实例化;
1. 提供一个公开的静态方法,判断成员变量是否为null,null则对成员变量进行实例化,不null则直接返回成员变量。

代码如下:

public class Singleton {
    //声明一个私有的静态成员变量
    private static Singleton sInstance;

    //将构造函数进行私有化
    private Singleton {
    }

    //提供一个公开的静态方法
    public static Singleton genInstance() {
        //对成员变量进行判空处理
        if (sInstance == null) {
            sInstance = new Singleton();
        }
        retrun sInstance;
    }
}

比较

饿汉模式与懒汉模式主要的不同点是饿汉模式是线程安全的,懒汉模式线程不安全,假设现在有两个线程,线程a调用getInstance方法时,当成员变量sInstance为null,且没有进行实例化时,线程b调用了genInstance方法,此时在系统中就会存在两个sInstance的实例,这样就出现了线程不安全。

优化懒汉模式

其实只需要把getInstance()变为同步(sychronized)方法,这种在多线程下线程不安全的问题就可以轻易解决。代码如下:

    public class Singleton {
        //声明一个私有的静态成员变量
        private static Singleton sInstance;

        //将构造函数进行私有化
        private Singleton {
        }

        //提供一个公开的静态方法
        public static synchronized Singleton genInstance() {
            //对成员变量进行判空处理
            if (sInstance == null) {
                sInstance = new Singleton();
            }
            retrun sInstance;
        }
    }

但是这样还是存在一种问题,其实只有在第一次执行此方法时,才需要同步,当成员变量sInstance实例化后,就不在需要同步这个方法了,之后每次调用这个方法,同步方法就成了累赘。

用“双重检查加锁”,减少同步的次数

利用双重检查加锁,首先检查是否实例已经创建了,如果未创建,才进行同步。这样一来,只有第一次会出现同步。代码如下:

        public class Singleton {
            //声明一个私有的静态成员变量
            private static volatile Singleton sInstance;

            //将构造函数进行私有化
            private Singleton {
            }

            //提供一个公开的静态方法
            public static Singleton genInstance() {
                //双重检查加锁
                if (sInstance == null) {
                    synchronized(Singleton.class) {
                        if (sInstance ==  null) {
                            sInstance = new Singleton();
                        }
                    }
                }
                retrun sInstance;
            }
        }

volatile关键字确保,当sInstance变量在进行实例化时,多个线程正确地处理sInstance变量。

定义

单例模式是确保一个类只有一个实例,并提供一个全局的访问入口。

类图

单例模式_第1张图片

你可能感兴趣的:(设计模式)