Java中的单例模式

单例模式是指某个类只能被实例化一次,用来表示全局或系统范围的组件,常用于日志记录,工厂,平台组件管理等。单例模式看似简单实际很难。

单例本身有多种实现方法,总体上可分为懒汉模式和饿汉模式两种,懒汉模式相对简单

public class FooSingleton {
    public final static FooSingleton INSTANCE = new FooSingleton();
    private FooSingleton() { }
    public void bar() { }
}

私有构造函数在楼初始化时调用且只调用一次,JVM保证在类完整初始化之后才会被其它多个线程调用。

饿汉模式常见线程安全的实现方式有三种:

  1. 双重检测加锁模式,注意Java中new FooSingleton()操作实际是有分配实例内存、引用指向内存地址,初始化实例3个原子操作组成。除了双重加锁外,必须要将实例instance定义为volatile类型防止指令重排才能保证完全正确。
  2. 静态内部类方法,内部类只有在它的静态方法、变量等被调用时才加载。
    public class FooSingleton4 {
        private FooSingleton4() {
        }
        public static FooSingleton4 getInstance() {
            return FooSingleton4Holder.INSTANCE;
        }
        private static class FooSingleton4Holder {
            private static final FooSingleton4 INSTANCE = new FooSingleton4();
        }
    }
  3. 使用枚举,根据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

猜你喜欢

转载自www.cnblogs.com/doit8791/p/8973756.html