Java设计模式

单例模式

2020-04-29  本文已影响0人  OakesYa

什么是单例模式

单例模式可以按照字面上的意思理解,保证类只有一个实例对象生成的模式。一般分为懒汉式和饿汉式,懒汉式中需要考虑下线程不安全的问题,可以在实例中展示

代码实例

懒汉式

public class SingletonHunger {
    private static SingletonHunger singletonHunger = new SingletonHunger();

    private static SingletonHunger getSingletonHunger() {
        return singletonHunger;
    }
}

我们可以看到因为singletonHunger变量是private和static修饰的,所以懒汉式其实就是项目启动的时候就初始化了对象并且外面并不能直接获取,必须通过getSingletonHunger方法获取,所以返回的都是已初始化完成的singletonHunger变量

饿汉式(非线程安全)

public class SingletonLazy {
    private static SingletonLazy singletonLazy;

    public static SingletonLazy getSingletonLazy() {
        if (singletonLazy == null) {
            singletonLazy = new SingletonLazy();
        }
        return singletonLazy;
    }
}

我们可以看到饿汉式并没有一开始就初始化对象,而是在获取对象方法中的时候判断一下对象是否已经初始化,但上面的代码其实存在并发风险,因为线程初始化并不是一个原子性的操作,当多个线程同时调用getSingletonLazy方法时很可能会多次初始化,所以我们可以改进一下代码

public class SingletonLazy {
    private static volatile SingletonLazy singletonLazy;

    public static synchronized SingletonLazy getSingletonLazy() {
        if (singletonLazy == null) {
            singletonLazy = new SingletonLazy();
        }
        return singletonLazy;
    }
}

第一种方法就是直接方法上加锁,这样可以保证线程的安全,但是我们使用的是方法锁,所有调用方都要竞争锁,所以我们可以再优化一版,改成对象锁

public class SingletonLazy {
    private static volatile SingletonLazy singletonLazy;

    public static SingletonLazy getSingletonLazy() {
        if (singletonLazy == null) {
            synchronized (SingletonLazy.class) {
                if (singletonLazy == null) {
                    singletonLazy = new SingletonLazy();
                }
            }
        }
        return singletonLazy;
    }
}

最终版的代码就写好了,我们仔细观察上面的代码会发现两个有意思的地方,一是singletonLazy变量增加了一个volatile修饰,二是方法中进行了两次是否为null的判断,为什么要这样做?

上一篇 下一篇

猜你喜欢

热点阅读