设计一个类, 我们只能生成该类的一个实例
1. 饿汉式
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Hungry { private AtomicLong atomicLong = new AtomicLong(); private Hungry(){ } private final static Hungry HUNGRY = new Hungry(); public static Hungry getInstance(){ return HUNGRY; } public long getId(){ return atomicLong.incrementAndGet(); } }
|
能防住多线程, 不能防住反射.
2. 懒汉式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Lazy{ private AtomicLong atomicLong = new AtomicLong(); private Lazy(){ System.out.println("one lazy singleton has been created"); } private static Lazy LAZY;
public static Lazy getInstance(){ if(LAZY == null){ LAZY = new Lazy(); } return LAZY; } public long getId(){ return atomicLong.incrementAndGet(); }
|
不能防住多线程, 不能防住反射.
3. 加锁懒汉式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class LockLazy{ private AtomicLong atomicLong = new AtomicLong(); private LockLazy(){ System.out.println("one locklazy singleton has been created"); } private static LockLazy LOCKLAZY; public static LockLazy getInstance(){ if(LOCKLAZY == null){ synchronized (LockLazy.class){ if(LOCKLAZY == null){ LOCKLAZY = new LockLazy(); } } } return LOCKLAZY; } public long getId(){ return atomicLong.incrementAndGet(); } }
|
4. 加锁加volatile懒汉式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class SafeLazy{ private AtomicLong atomicLong = new AtomicLong(); private volatile static SafeLazy SAFELAZY; private SafeLazy(){ }
public static SafeLazy getInstance(){ if(SAFELAZY == null) { synchronized (SafeLazy.class) { if(SAFELAZY == null) { SAFELAZY = new SafeLazy(); } return SAFELAZY; } } return SAFELAZY; } public long getId(){ return atomicLong.incrementAndGet(); } }
|
多线程足够安全, 仍然防不住反射
5. 静态内部类实现单例模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class Holder { private Holder(){
} private AtomicLong atomicLong = new AtomicLong(); private static class InnerClass { private static final Holder HOLDER = new Holder(); } public static Holder getInstance(){ return InnerClass.HOLDER; } public long getId(){ return atomicLong.incrementAndGet(); } }
|
就是把饿汉式的new 单例模式的过程private final static Hungry HUNGRY = new Hungry();放到个静态内部类中, 通过静态内部类的加载机制实现懒惰加载. 仍然防不住反射
6. 枚举类实现单例模式
1 2 3 4 5 6 7 8 9 10 11 12
| enum Singleton { SINGLETON; private AtomicLong atomicLong = new AtomicLong(); public long getId(){ return atomicLong.incrementAndGet(); } public static Singleton getInstance() { return SINGLETON; } }
|
这个最安全, 多线程和反射都破坏不了, 反序列化的方法也破解不了. 也最简洁, 核心代码只需要3行. 加载模式和饿汉式一样, 都是提前加载. 怪不得都推荐使用这种方法