栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

设计模式-单例模式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

设计模式-单例模式

饿汉单例

优点:绝对线程安全,实现简单

缺点:类加载时就实例化,如果单例数量众多,浪费内存。

public class HungrySingleton {
    private static final HungrySingleton INSTANCE = new HungrySingleton();

    private HungrySingleton() {
    }

    public static HungrySingleton getInstance() {
        return INSTANCE;
    }
}
懒汉单例

优点:延迟加载,只有使用的时候才实例化

缺点:加锁,影响性能

写法一(锁双重校验):

public class LazySingleton {
    //volatile避免指令重排:实例化时3先执行,其它线程满足instance!=null,但使用实例的时候堆空间还未初始化就会报错
    private volatile static LazySingleton instance;

    private LazySingleton() {
    }

    public static LazySingleton getInstance() {
        if (instance != null) {
            return instance;
        }
        synchronized (LazySingleton.class) {
            //双重校验
            if (instance != null) {
                return instance;
            }
            //1开辟堆空间-》2堆空间初始化-》3引用指向空间地址
            instance = new LazySingleton();
        }
        return instance;
    }
}

写法二(静态内部类):

public class InnerClassSingleton {
    private InnerClassSingleton() {
    }

    public InnerClassSingleton getInstance() {
        return LazyHolder.INSTANCE;
    }

    private static class LazyHolder {
        public final static InnerClassSingleton INSTANCE = new InnerClassSingleton();
    }
}
容器化单例

个人理解,和懒汉思想一样,只是通过map来保存实例而已。

public class ContainerSingleton {
    private ContainerSingleton() {
    }

    private static Map map = new ConcurrentHashMap<>();

    public static Object getInstance(String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        if (map.containsKey(className)) {
            return map.get(className);
        }
        synchronized (map) {
            if (map.containsKey(className)) {
                return map.get(className);
            }
            Object obj = Class.forName(className).newInstance();
            map.put(className, obj);
            return obj;
        }
    }
}

但以上单列都有一个共同的缺点,就是可以被反射(在构造函数中加逻辑判断可以防止反射破坏)和序列化破坏(增加readResolve()方法避免序列化破坏)。于是就有了枚举单列的出现。

readResolve原理:在反序列化的时候,如果存在readResolve方法,就会使用这个方法返回的实例,丢弃新生成的实例,缺点就是有新生成的实例,虽然丢弃了,但是还是浪费内存。

枚举单列

优点:线程安全,可避免反射和序列化破坏单列,写法简单优雅

缺点:类加载时就实例化,和饿汉一样,大量单列的情况下对内存不友好。

public enum EnumSingleton {
    INSTANCE;

    public static EnumSingleton getInstance() {
        return INSTANCE;
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/531094.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号