饿汉模式
特点:基于类加载机制, 避免了多线程的同步问题,在类加载时期就已经生成。所以必定只有唯一一个。同时会降低类加载速度,而且如果这个实例不会被使用,会造成内存浪费。
1 2 3 4 5 6 7
| public class Singleton{ private static Singleton instance = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return instance; } }
|
懒汉模式(线程不安全)
1 2 3 4 5 6 7 8 9 10 11
| public class Singleton{ private static Singleton instance; private static Singketon(){ } public static Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }
|
懒汉模式(线程安全)
1 2 3 4 5 6 7 8 9 10
| public class Singleton{ private static Singleton instance; private Singleton(){} public static synchronized Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }
|
双重检查模式(DCL)
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Singleton{ private volatile static Singleton singleton; private Singleton(){} public static Singleton getInstance(){ if(instance == null){ synchronized (Singleton.class){ if(instance == null){ instance = new Singleton(); } } } } }
|
静态内部类
特点:首先我们要明确一点,类加载的时候,外部类中的静态内部类是不会被加载的,只有在被调用的时候才会被加载。
这也是静态内部类方法区别于饿汉模式的地方。只有在 getInstance()
方法被调用后,才会产生实例,且唯一。
1 2 3 4 5 6 7 8 9
| public class Singleton{ private Singleton(){} public static Singleton getInstance(){ return SingletonHolder.sInstance; } private static class SingletonHolder{ private static final Singleton sInstance = new Singleton(); } }
|
枚举单例
1 2 3 4 5 6
| public enum Singleton{ INSTANCE; public void doSomeThing(){ ... } }
|
使用场景
- 整个项目需要一个共享访问点或共享数据
- 创建一个对象需要消耗的资源过多, 比如访问 I/O 或者数据库等资源。
- 工具类对象