设计模式之单例模式

单例模式

有什么用处

有些对象其实我们只需要一个,比方说:线程池,缓存,对话框,注册表,日志对象...如果制造出多个实例,就会导致许多问题产生,例如程序的行为异常,资源使用过量,数据不一致

如何做

利用静态类变量,静态方法和适当的访问修饰符

定义

单例模式,确保一个类只有一个实例,并提供一个全局访问点

注意点,多线程中使用单例

如果有多个线程同时调用getInstance(),可能会产生多个实例,那就用synchronized(同步)关键字修饰 但是同步会降低性能,实际上也就第一次getInstance()时需要考虑同步问题,之后就没有同步问题.

1.如果getInstance()的性能对应用程序不是很关键,就加上synchronized关键字

/**
 * 单例模式之懒汉模式
 * 优点:在需要实例的时候才进行第一次实例化,在资源紧缺的时候,可以减少不必要的资源消耗
 * 缺点:同步了getInstance(),会造成性能浪费
 */
public class SingletonLazy {
    /**
     * 利用一个静态变量来记录Singleton类的唯一实例
     */
    private static SingletonLazy instance;

    /**
     * 构造器声明为私有的,只有自己Singleton类才可以调用构造器
     */
    private SingletonLazy() {

    }

    /**
     * 用getInstance()实例化对象,并返回这个实例
     * 在多线程中必须使用synchronized关键字修饰
     * @return
     */
    public static synchronized SingletonLazy getInstance() {

        //懒汉模式
        //如果未被实例化,则new
        if (instance == null) {
            instance = new SingletonLazy();
        }
        //如果已经实例化,则返回实例
        return instance;
    }
}

2.如果getInstance()的性能对应用程序很关键,那就使用饿汉模式

使用饿汉模式

public class SingletonLazy{
    //在静态初始化器(static initialize)中创建单例.这段代码保证了线程安全(Thread Safe)
    private static SingletonLazy instance=new SingletonLazy();

    private SingletonLazy(){
    }

    public static SingletonLazy getInstance(){
        //到这里,一定存在实例了,直接使用它
        return instance;
    }

}

3.使用"双重检查锁"(double-checked locking),在getInstance()中减少使用同步

/**
 * 单例模式之使用"双重检查加锁"
 * 过程:在getInstance()中进行双重检查,确保一个实例
 * 优点:在getInstance()中减少同步,增强性能,可以在多线程中使用
 * 缺点:暂无
 */
public class SingletonDoubleCheckedLocking {
    /**
     * 利用一个静态变量来记录Singleton类的唯一实例
     * volatile关键字确保:当instance变量被初始化为Singleton实例时,多个线程正确地处理instance变量
     */
    private static volatile SingletonDoubleCheckedLocking instance;

    /**
     * 构造器声明为私有的,只有自己Singleton类才可以调用构造器
     */
    private SingletonDoubleCheckedLocking() {
    }

    /**
     * 用getInstance()实例化对象,并返回这个实例
     * 方法不必用synchronized关键字修饰
     * @return
     */
    public static SingletonDoubleCheckedLocking getInstance() {
        if(instance==null){//检查实例,如果不存在,则进入同步区块
            //注意:只有第一次调用getInstance()方法才彻底执行这里的代码
            synchronized (SingletonDoubleCheckedLocking.class){
                if(instance==null){//进入区块后,再检查一次,如果是null,才创建实例
                    instance=new SingletonDoubleCheckedLocking();
                }
            }
        }

        return instance;
    }
}

项目地址

java设计模式实现 如果觉得有点收获,记得在项目上点star哦!

Posted on Categories java Tags