public class Singleton { /** * 线程安全,因为jvm在加载类时,对static的属性只能有一个线程执行一次 * 比较复杂的创建过程可以放在static{}里面 */ private static Singleton instance = new Singleton(); private Singleton() {} private static Singleton getInstance() { return instance; } }
写法二:
public class LazySingleton { private static LazySingleton instance = null; private LazySingleton() {} /* * 在使用的时候创建实例 * 需要用synchronized来保证线程安全,不过对整个方法都加了锁,性能不高 */ private static synchronized LazySingleton getInstance() { if(instance == null) { instance = new LazySingleton(); } return instance; } }
写法三:
public class LazyClassSingleton { private LazyClassSingleton() {} /* * 利用内部类的静态变量创建实例,也是延迟创建 */ private static class SingletonHolder { private static final LazyClassSingleton instance = new LazyClassSingleton(); } private LazyClassSingleton getInstance() { return SingletonHolder.instance; } }
写法四:
public class DoubleCheckSingleton { /* * volatile关键字具有synchronized的可见性特点, * 线程能够自动发现volatile变量的最新值 */ private volatile static DoubleCheckSingleton instance = null; private DoubleCheckSingleton() {} private static synchronized DoubleCheckSingleton getInstance() { if (instance == null) { //第一次检查,如果不为空,则没必要加锁,直接返回 synchronized (DoubleCheckSingleton.class) { if (instance == null) { //加锁后的第二次检查,确认对象的确还没被创建 instance = new DoubleCheckSingleton(); } } } return instance; } }
关于单例模式的序列化:
/* * 实现序列化接口的单例类每次被反序列化后都会返回一个新建的实例, * 必须实现readResolve方法将返回的实例指向当前的对象 * 这样当JVM从内存中反序列化地"组装"一个新对象时, * 就会自动调用这个 readResolve方法来返回我们指定好的对象了, 单例规则也就得到了保证 */ public class SerialibleSingleton implements Serializable { private static final long serialVersionUID = -60684598518739226L; private static SerialibleSingleton instance = new SerialibleSingleton(); private SerialibleSingleton() {} private static SerialibleSingleton getInstance() { return instance; } private Object readResolve() { return instance; } }