单例模式java

下面是从一个不单例的代码逐步优化成单例的代码的过程。

1、两个类的关系为依赖关系

在一个类A的普通方法中new目标对象,多次执行方法,会创建多个目标对象。

//todo

2、两个类的关系由依赖变关联

扩大目标对象的作用域到普通方法外,在类A的范围内声明一个目标对象,在普通方法中使用目标对象前判断是否已经实例化,如果没有再实例化,否则直接使用。如果有多个类A对象,也会创建多个目标对象。此时目标对象还不是全局单例。

//todo

3、构造函数创建对象

接下来还怎么扩大作用域范围呢?把目标对象声明到哪里,在使用的时候能拿到唯一的实例呢?已经把目标对象的声明由调用方类A的方法内扩大到了它的类内,如果再往其他类C中实例化,在类A中使用,一来不合适,二来new多个类C,同样会有多个目标对象。所以放在调用方类的范围内实例化不能满足需求了。那放在目标对象类本身呢?一个类new不new对象,由它自己说了算。可以,把构造函数变私有,其他类不能去实例化它,只有它自己可以实例化,当不存在实例时再去创建。接下来再提供一个静态公有方法返回它的实例。所有其他类都通过静态公有方法获得目标对象。

//todo

4、多线程单例

多线程时如何保证单例呢?把获取单例对象的静态方法加锁,保证同一时刻只能有一个线程获取实例对象。这样足够了吧?还不行?获取对象会影响性能?还能怎么办?把锁粒度再小一点?

//todo

5、双重锁-懒汉式

锁粒度再小,由锁方法到锁对象?锁方法里的一个分支的代码,锁判断对象是否为创建,未创建则创建的代码。

给Singleton.class加synchronized锁,不太理解是什么意思?

instance属性加上volatile是什么意思?

//todo

以上是双重锁定方式,保证多线程时也单例,称为懒汉式加载

6、饿汉式

下面是饿汉式加载,上来就给静态的Singleton变量实例化,获取实例的方法直接返回此实例。

//todo

在Java中,单例模式的演变过程如下:

1. 1、简单单例模式:

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

2. 2、考虑多线程,使用同步方法:

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

3. 3、考虑性能,使用同步代码块:

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                } 
            }
        }
        return instance;
    }
}

4. 4、进一步提高性能,使用双检查锁定:

public class Singleton {
    private volatile static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) { 
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
} 

5. 5、使用枚举实现单例:

public enum Singleton {
    INSTANCE;

    public void doSomething() {
        ...
    }
}

这个是Java中单例模式的演变过程,从简单模式考虑多线程性能问题,最终使用枚举实现一个线程安全的单例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值