一个类只有一个实例存在,同时提供能对该实例加以访 问的静态访问方法。
单例模式网上有好几个实现方式,其中比较耳熟的是一下三种: 1 饿汉模式 2 懒汉模式 3 双重检查 其中懒汉模式线程不安全,饿汉模式与双重检查是线程安全的,双重检查是在懒汉模式的基础上做修改,达到线程安全的目的。 还有两种推荐使用的模式: 1 静态内部类实现 2 枚举实现
饿汉模式是在类加载时创建对象,线程安全。
//饿汉模式 public class Singleton { private static final Singleton singleton = new Singleton(); private Singleton(){}; public static Singleton getInstance(){ return singleton; } }懒汉模式为等到第一次需要该类实例时才创建对象,线程不安全。
//懒汉模式 public class Singleton { private static Singleton singleton; private Singleton(){}; public static Singleton getInstance(){ if(null == singleton){ singleton = new Singleton(); } return singleton; } }双重检查是在懒汉模式基础上做修改,使得它线程安全。 双重判断比起方法加锁的好处是对象创建完成后对对象是否存在的判断不需要上锁,效率高。
//双重检查 public class Singleton { private static volatile Singleton singleton; private Singleton(){}; public static Singleton getInstance(){ if(null == singleton){ synchronized(Singleton.class){ if(null == singleton){ singleton = new Singleton(); } } } return singleton; } } /* singleton=new Singleton()对象的创建在JVM中可能会进行重排序,使用volatile修饰signleton实例变量有效解决该问题。 */安全且在多线程情况下能保持高性能。
//静态内部类实现 public class Singleton { private Singleton() { } static class inner { private static final Singleton singleton = new Singleton(); } public static Singleton getInstance() { return inner.singleton; } }枚举类实例的创建也是线程安全的,所以使用枚举来实现单例也是一种比较推荐的方法
//枚举实现 public enum Singleton { INSTANCE; private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } // 调用时使用Singleton.INSTANCE.setName()即可