Map中的单例模式

​ 实现懒汉式单例模式,我们通常使用以下两种方式实现。

静态内部类

public class Singleton {
    
    private Singleton() {
    }

    private static class SingletonHoler {
        private static Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHoler.INSTANCE;
    }
    
}

双重检查锁

public class Singleton {
    
    private static volatile Singleton INSTANCE = null;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (Objects.isNull(INSTANCE)) {
            synchronized (Singleton.class) {
                if (Objects.isNull(INSTANCE)) {
                    INSTANCE = new Singleton();
                }
            }
            return INSTANCE;
        }
    }
}

​ 如果需要创建多个单例对象,也就是map中的value需要实现单例模式,有哪些实现方式?

静态内部类不可行
显然静态内部类适用于属性为固定值的对象,对于拥有可变属性的对象并不适合。

redis不可行
因为redis在进行读取的时候需要进行序列化和反序列化,而每次反序列化都是创建一个新的对象。

双重检查锁可行,但是麻烦
双重检查锁有一个关键的步骤就是给单例对象的引用设置volatile,使得该引用的赋值禁止重排序,从而保证引用对象的可见性。因为volatile无法修饰局部变量,所以需要定义成员变量作为中介。

public class AccountRepository {

    // 数据库
    AccountDb accountDb = new AccountDb();

    // 缓存
    Map<Integer, Account> cache = new ConcurrentHashMap();

    // 因为volatile无法修饰局部变量所以定义了成员变量
    volatile Account account;
    
    public Account getById(int id) {
        if (!cache.containsKey(id)) {
            // 缓存中不存在,那么就创建
            initCache(id);
        }
        return cache.get(id);
    }

    private synchronized void initCache(int id) {
        if (!cache.containsKey(id)) {
            account = accountDb.getById(id);
            cache.put(id, account);
            account = null;
        }
    }

}

ConcurrentHashMap.computeIfAbsent可行
ConcurrentHashMap.computeIfAbsent内部通过Unsafe类已经实现了变量的可见性处理。

public class AccountRepository {

    // 数据库
    AccountDb accountDb = new AccountDb();

    // 缓存
    Map<Integer, Account> cache = new ConcurrentHashMap();

    public Account getById(int id) {
        if (!cache.containsKey(id)) {
            initCache(id);
        }
        return cache.get(id);
    }

    private void initCache(int id) {
        cache.computeIfAbsent(id, key -> accountDb.getById(key));
    }

}

ConcurentHashMap部分代码

public class ConcurrentHashMap<K,V>{
    
    private static final sun.misc.Unsafe U;
    
    static final <K,V> void setTabAt(Node<K,V>[] tab, int i, Node<K,V> v) {
        // 通过unsafe类来赋值,实现可见性赋值,禁止重排序
        U.putObjectVolatile(tab, ((long)i << ASHIFT) + ABASE, v);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值