单例模式是指某个类只能被实例化一次, 用来表示全局或系统范围的组件, 常用于日志记录, 工厂, 平台组件管理等. 单例模式看似简单实际很难.
单例本身有多种实现方法, 总体上可分为懒汉模式和饿汉模式两种, 懒汉模式相对简单
- public class FooSingleton {public final static FooSingleton INSTANCE = new FooSingleton();
- private FooSingleton() { }
- public void bar() { }
- }
私有构造函数在楼初始化时调用且只调用一次, JVM 保证在类完整初始化之后才会被其它多个线程调用.
饿汉模式常见线程安全的实现方式有三种:
双重检测加锁模式, 注意 Java 中 new FooSingleton() 操作实际是有分配实例内存, 引用指向内存地址, 初始化实例 3 个原子操作组成. 除了双重加锁外, 必须要将实例 instance 定义为 volatile 类型防止指令重排才能保证完全正确.
静态内部类方法, 内部类只有在它的静态方法, 变量等被调用时才加载.
- public class FooSingleton4 {
- private FooSingleton4() {
- }
- public static FooSingleton4 getInstance() {
- return FooSingleton4Holder.INSTANCE;
- }
- private static class FooSingleton4Holder {
- private static final FooSingleton4 INSTANCE = new FooSingleton4();
- }
- }
使用枚举, 根据 Java 语言规范 8.9,"Enum 的 final 克隆方法保证枚举永远无法被克隆, 其特殊的序列化机制保证无法反序列化得到拷贝的对象. 同时, 还禁止利用反射对枚举进行实例化. 保证了这四个方面, 在枚举常量之外, 就不会有其他同类的枚举实例存在."
- public enum FooEnumSingleton {
- INSTANCE;
- public static FooEnumSingleton getInstance() { return INSTANCE; }
- public void bar() { }
- }
要想真正实现单例, 防止出现多个实例, 还要考虑无法单例无法通过 clone 方法被克隆, 无法通过序列化反序列化被拷贝, 无法通过反射被重新序列化等. 现在一般多推荐采用单例的写法, 不仅代码简洁, 相对来说也能更好的预防上述问题.
http://www.importnew.com/16995.html
来源: http://www.bubuko.com/infodetail-2581450.html