单例设计模式( Singleton Design Pattern):一个类只允许创建一个对象(或者实例),那这个类就是一个单例类,这种设计模式就叫作单例设计模式,简称单例模式。
饿汉式
public class HungrySingleton {private AtomicLong generator = new AtomicLong(0);//初始化加载,禁止重新赋值private static final HungrySingleton instance = new HungrySingleton();//禁止创建新对象private HungrySingleton() {}//唯一实例获取public static HungrySingleton getInstance() {return instance;}//功能public long getNextId() {return generator.getAndIncrement();}}
懒汉式
并发度太低
public class LazySingleton {private AtomicLong generator = new AtomicLong(0);private static LazySingleton instance = null;//禁止外部创建private LazySingleton() {}//加锁,只创建一次//类锁,保证同一个类只有一个对象public static synchronized LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}public long getNextId() {return generator.getAndIncrement();}}
双重检测
解决懒汉式并发度低的问题
public class DCSingleton {private AtomicLong generator = new AtomicLong(0);//private static DCSingleton instance = null;private DCSingleton() {}//只有没有实例化时候加锁,增加了并发度//类锁public static DCSingleton getInstance() {if (instance == null) {synchronized (DCSingleton.class) {if (instance == null) {instance = new DCSingleton();}}}return instance;}public long getNextId() {return generator.getAndIncrement();}}
有人说,这种写法会由于指令重排,在实例化后赋值给instance后还没有来得及初始化(调用构造函数中的初始化逻辑)就被其他线程调用,所以需要加上volatile字段。 实际上在高版本(1.5以后)java中已经解决了这个问题(让new操作和初始化操作设计为原子操作),因此不需要加volatile字段
静态内部类
public class StaticInnerSingleton {private StaticInnerSingleton instance = null;private AtomicLong generator = new AtomicLong(0);public static class SingletonHolder {public static final StaticInnerSingleton instance = new StaticInnerSingleton();}public static StaticInnerSingleton getInstance() {return SingletonHolder.instance;}public long getNextId() {return generator.getAndIncrement();}}
外部类加载时候,内部类不会实例化;只有当调用 getinstance0方法时, Singletonholderオ会被加载,这个时候才会创建 instance。 insance的唯性、创建过程的线程安全性,都由JVM来保证。所以,这种实现方法既保证了线程安全,又能做到延退加载。
public enum EnumSingleton {INSTANCE;private AtomicLong generator = new AtomicLong(0);public long getNextId() {return generator.getAndIncrement();}}
