响应式编程群交流 之 单例模式讨论

457 阅读3分钟

单例的实现

不追求那么多花哨的,直接给两个最实际的用法: 懒汉模式的实现(上海-kotlin-kevin 提供):

public final class Foo {

    private static class FooLoader {
        private static final Foo INSTANCE = new Foo();
    }

    private Foo() {
        if (FooLoader.INSTANCE != null) {
            throw new IllegalStateException("Already instantiated");
        }
    }

    public static Foo getInstance() {
        return FooLoader.INSTANCE;
    }
}

点评:

重庆-java-渣渣:你这用的是静态内部类,在效率和安全性上都比起其他的好。

本人追加:静态内部类和非静态内部类一样,都是在被调用时才会被加载,以此来实现懒汉模式。所用环境,在单例对象占用资源大,需要延时加载的情况下优选。

饿汉模式的实现(本人提供):

//reactor.netty.resources.DefaultLoopNativeDetector
final class DefaultLoopNativeDetector {

	private static final DefaultLoop INSTANCE;

	static {
		if (DefaultLoopKQueue.hasKQueue()) {
			INSTANCE = new DefaultLoopKQueue();
		}
		else if (DefaultLoopEpoll.hasEpoll()) {
			INSTANCE = new DefaultLoopEpoll();
		}
		else {
			INSTANCE = new DefaultLoop() {};
		}
	}

	public static DefaultLoop getInstance() {
		return INSTANCE;
	}
}

杭州_java_小狼: 反射可以破坏任何形式的单例,想着防止被反射破坏单例,几乎不大可能,不如想想怎么正常使用反射。 反射去获取单例,不是单例的正常使用方式。按照单例的设计规则,获取该实例应该由该类自行提供获取实例的方法,也就是熟悉的getInstance方法。反射去调单例模式,说明这个场景已经不适用单例了。

本人:为什么用单例,它的场景在哪里?

杭州_java_小狼:为什么要使用单例?在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率(也就是常说的性能优化,代码优化吧)。 它的场景,我觉得主要是要面对共享资源的访问与操作,以及控制资源的访问与操作时,可以考虑使用单例模式。

本人:说白了就是当下容器里的唯一。这个唯一该如何表达,容器生它生,还是容器有用到的时候才有。前者的话就在类加载的时候就给它实例化,也就是说,饿汉式,后者涉及到懒加载也就是懒汉式。

杭州_java_小狼: 这个应该涉及到了实例化的延迟与否,容器有它有是饿汉式加载,容器用到的时候才有是懒加载。 本人: 现在内存这么大,基本饿汉式就可以了。所谓的设计模式从来都是从使用场景出发的。

小狼:关于你说的单例的相对唯一性

杭州_java_小狼: 比如,在一个应用中我们使用了Spring,那么Spring作为一个容器,里面的单例是相对Spring容器中的单例;假如这个Sping的应用又部署在Docker容器中,那这个单例的相对唯一性会改变吗? 也就是,在Docker容器的范围内,是否允许出现一个单例对象的两个实例?一个出现在Spring容器中,一个出现在Docker的另外一个地方。 好像记得你分享的时候,说过类似的问题,具体是怎么回事挤不太清楚了。

本人:一个tomcat下可以放置多个web项目,你看彼此是不是独立的。

杭州_java_小狼: 多谢知秋大哥,你这么讲,我就明白了。

更多精彩请加入QQ群:响应式编程交流 523409180

相关讨论成员博客:

杭州_java_小狼www.jianshu.com/u/0ab97f4c6…